rules/nuxt/patterns.md
This file extends common/patterns.md with Nuxt specific content.
Load-bearing. Pick by render timing, not habit.
useFetch(url) = SSR-safe, URL-first initial/first-paint data. The default. Forwards the server result through the payload so there is no hydration double-fetch.useAsyncData(key, fn) = SSR-safe, custom async logic (SDK / GraphQL / combined calls). The explicit key shares the result across components.$fetch = client interactions only (form submit, button click, POST/PUT/DELETE). NOT SSR-safe, double-fetches if used for first paint.useFetch / useAsyncData for anything rendered on first paint, $fetch only for event-driven mutations.useState('key', () => init) for SSR-safe shared state. Values must be JSON-serializable.export const x = ref() at module scope. One shared instance leaks across concurrent SSR requests and causes a memory leak.@pinia/nuxt: Pinia for domain state, useState for small cross-component primitives.callOnce(async () => {...}), not as a side effect inside useAsyncData.server/api/*.{get,post}.ts auto-register by path + method. Handler is defineEventHandler((event) => ...).throw createError({ status, statusText }). Prefer the Web-API status / statusText over deprecated statusCode / statusMessage.server/middleware/ must NOT return a response. Only mutate event.context or set headers.app/middleware/*.ts with defineNuxtRouteMiddleware((to, from) => ...).to / from args. Do NOT call useRoute() inside middleware..global suffix runs on every route. Return navigateTo() to redirect, abortNavigation() to stop.status (idle | pending | success | error) for lazy fetches.useAsyncData payload uses devalue (Date/Map/Set/refs survive). A server/api response is JSON.stringify-only, so define toJSON() for non-JSON types.pick / transform. This reduces serialized size, it does not skip the fetch.nuxt4-patterns, vite-patterns, frontend-patterns.