Nuxt.js
02 / 02

Server Routes, Rendering Modes & Modules

Server Routes, Rendering Modes & Modules

Server API Routes (Nitro)

// server/api/users.ts — becomes GET /api/users
export default defineEventHandler(async (event) => {
  const users = await db.user.findMany()
  return users
})

// server/api/users/[id].ts — dynamic segment
export default defineEventHandler(async (event) => {
  const id = getRouterParam(event, 'id')
  return await db.user.findUnique({ where: { id } })
})

// Server-only code — never bundled to the client, unlike a component import
// server/utils/db.ts is only ever imported from files under server/

Hybrid Rendering with routeRules

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    '/': { prerender: true },              // static at build time
    '/blog/**': { swr: 3600 },             // cached, revalidated hourly
    '/dashboard/**': { ssr: true },        // always server-rendered, fresh
    '/admin/**': { ssr: false },           // client-only (SPA mode for this route)
  },

  runtimeConfig: {
    apiSecret: '',                // server-only — read from NUXT_API_SECRET env var
    public: {
      apiBase: '/api',            // exposed to client — read from NUXT_PUBLIC_API_BASE
    },
  },

  modules: ['@pinia/nuxt', '@nuxtjs/tailwindcss'],
})

Middleware & Plugins

// middleware/auth.ts — named middleware, opted into via definePageMeta
export default defineNuxtRouteMiddleware((to) => {
  const user = useState('user')
  if (!user.value) {
    return navigateTo('/login')
  }
})

// plugins/sentry.client.ts — .client suffix ensures browser-only execution
export default defineNuxtPlugin((nuxtApp) => {
  Sentry.init({ dsn: 'https://...' })
})

// Avoiding hydration mismatches — guard non-deterministic/browser-only values
// with onMounted so they only run AFTER hydration, not during SSR:
// const clientOnlyValue = ref(null)
// onMounted(() => { clientOnlyValue.value = window.innerWidth })

Static Generation

nuxt generate   # pre-renders every route to static HTML at build time
                # — deployable to any static host, no server runtime needed
                # trade-off: content changes need a new build to appear,
                # unlike SSR which always reflects current data per-request

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free