`), and
non-deterministic iteration order.
Fix kit: wrap genuinely client-only UI in `
`; branch with `import.meta.client` /
`import.meta.server`; do browser work in `onMounted` (never in `setup` body); and pin a
server-generated value with `useState` so the client reuses the exact same value instead of
recomputing it.
```vue
```
## Nitro server routes
Files in `server/api/*` and `server/routes/*` run on Nitro (Nuxt's server engine). Name by method
with `.get.ts`/`.post.ts`. Validate input; throw `createError` for HTTP errors.
```ts
// server/api/products/[id].get.ts
export default defineEventHandler(async (event) => {
const id = getRouterParam(event, 'id')
const { fields } = getQuery(event)
if (!id) throw createError({ statusCode: 400, statusMessage: 'id required' })
const config = useRuntimeConfig() // private keys server-only
const data = await fetchFromDb(id, config.dbUrl)
if (!data) throw createError({ statusCode: 404, statusMessage: 'Not found' })
return data
})
```
`useRuntimeConfig()` exposes top-level keys **only on the server**; only `config.public.*` reaches
the browser bundle. Rule: a secret in `runtimeConfig.public` (or any `NUXT_PUBLIC_*` env) ships to
every client — keep API keys, DB URLs, and tokens at the top level, never under `public`. Type
calls to your own API with `$fetch('/api/...')`. Handlers, route-rule recipes,
middleware, and `defineCachedEventHandler` caching live in
[`references/nitro-and-rendering.md`](references/nitro-and-rendering.md).
## Rendering strategy
Set per-route rendering in `nuxt.config.ts` with `routeRules`; the right mix is usually hybrid,
not all-SSR.
```ts
export default defineNuxtConfig({
routeRules: {
'/': { prerender: true }, // SSG at build
'/blog/**': { swr: 3600 }, // stale-while-revalidate cache 1h
'/products/**': { isr: true }, // incremental static regeneration
'/admin/**': { ssr: false }, // client-only SPA island
'/old': { redirect: '/new' },
'/api/**': { headers: { 'cache-control': 's-maxage=60' } },
},
})
```
`nuxt build` produces an SSR server; `nuxt generate` prerenders a fully static site. The **Nitro
preset** chooses the deploy target (node-server, vercel, netlify, cloudflare-pages, …) — pick the
preset here, then hand platform specifics to [`deployment`](../deployment/SKILL.md),
[`vercel`](../vercel/SKILL.md), [`netlify`](../netlify/SKILL.md), or
[`cloudflare`](../cloudflare/SKILL.md).
## Performance
- `shallowRef`/`shallowReactive` for large payloads/lists — skip deep proxy cost; replace the whole
value to update. Why: deep reactivity on a 10k-row array is pure overhead.
- `v-memo` to freeze a subtree on stable deps; `v-once` for render-once static content.
- `defineAsyncComponent` and Nuxt's auto `Lazy` prefix to code-split below the fold.
- `` / `@nuxt/image` for responsive, optimized images (a top LCP lever).
- Shrink the SSR payload with `pick`/`transform` on `useFetch`/`useAsyncData`.
- Vue 3.6 **Vapor Mode** (compile-time, no-VDOM, opt-in per component via `