nuxt4-patterns/SKILL.md
Nuxt 4 app patterns for hydration safety, performance, route rules, lazy loading, and SSR-safe data fetching with useFetch and useAsyncData.
npx skillsauth add lidge-jun/cli-jaw-skills nuxt4-patternsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Nuxt 3 EOL: July 31, 2026. Migrate to Nuxt 4 before that date to continue receiving security patches.
Use when building or debugging Nuxt 4 apps with SSR, hybrid rendering, route rules, or page-level data fetching.
useFetch, useAsyncData, or $fetchapp/ convention)Nuxt 4 moves application source into an app/ directory, cleanly separating app code from project config:
project-root/
├── app/ # Application source (Nuxt 4 default)
│ ├── assets/
│ ├── components/
│ ├── composables/
│ ├── layouts/
│ ├── middleware/
│ ├── pages/
│ ├── plugins/
│ └── app.vue
├── public/
├── server/ # Server routes & API (stays at root)
├── shared/ # Code shared between app/ and server/
├── nuxt.config.ts
└── package.json
The shared/ directory is for utilities, types, and constants used by both client and server code.
Date.now(), Math.random(), browser-only APIs, or storage reads directly into SSR-rendered template state.onMounted(), import.meta.client, ClientOnly, or a .client.vue component when the server cannot produce the same markup.useRoute() composable, not the one from vue-router.route.fullPath to drive SSR-rendered markup. URL fragments are client-only, which can create hydration mismatches.ssr: false as an escape hatch for truly browser-only areas, not a default fix for mismatches.await useFetch() for SSR-safe API reads in pages and components. It forwards server-fetched data into the Nuxt payload and avoids a second fetch on hydration.useAsyncData() when the fetcher is not a simple $fetch() call, when you need a custom key, or when you are composing multiple async sources.useAsyncData() a stable key for cache reuse and predictable refresh behavior.useAsyncData() handlers side-effect free. They can run during SSR and hydration.$fetch() for user-triggered writes or client-only actions, not top-level page data that should be hydrated from SSR.lazy: true, useLazyFetch(), or useLazyAsyncData() for non-critical data that should not block navigation. Handle status === 'pending' in the UI.server: false only for data that is not needed for SEO or the first paint.pick and prefer shallower payloads when deep reactivity is unnecessary.const route = useRoute()
const { data: article, status, error, refresh } = await useAsyncData(
() => `article:${route.params.slug}`,
() => $fetch(`/api/articles/${route.params.slug}`),
)
const { data: comments } = await useFetch(`/api/articles/${route.params.slug}/comments`, {
lazy: true,
server: false,
})
useFetch FactoriesCreate typed, preconfigured fetch composables to reduce boilerplate and enforce API conventions:
// composables/useApiFetch.ts
export function useApiFetch<T>(path: string, opts: Parameters<typeof useFetch>[1] = {}) {
return useFetch<T>(path, {
baseURL: '/api',
headers: { 'X-App-Version': useRuntimeConfig().public.appVersion },
...opts,
})
}
This keeps auth headers, base URLs, and error handling consistent across all data-fetching calls.
Nuxt 4 ships with Vue Router v5, which adds:
useRoute('users-id') gives typed params.id without manual casting.useRouteQuery: A reactive composable for reading and writing query parameters.(group)/ directory names — the group name is stripped from the URL.Prefer the Nuxt useRoute() / useRouter() composables which wrap Vue Router v5 with SSR-safe behavior.
Prefer routeRules in nuxt.config.ts for rendering and caching strategy:
export default defineNuxtConfig({
routeRules: {
'/': { prerender: true },
'/products/**': { swr: 3600 },
'/blog/**': { isr: true },
'/admin/**': { ssr: false },
'/api/**': { cache: { maxAge: 60 * 60 } },
},
})
prerender: static HTML at build timeswr: serve cached content and revalidate in the backgroundisr: incremental static regeneration on supported platformsssr: false: client-rendered routecache or redirect: Nitro-level response behaviorPick route rules per route group, not globally. Marketing pages, catalogs, dashboards, and APIs usually need different strategies.
Lazy prefix to dynamically import non-critical components.v-if so the chunk is not loaded until the UI actually needs it.<template>
<LazyRecommendations v-if="showRecommendations" />
<LazyProductGallery hydrate-on-visible />
</template>
defineLazyHydrationComponent() with a visibility or idle strategy.NuxtLink for internal navigation so Nuxt can prefetch route components and generated payloads.<NuxtRouteAnnouncer>: Built-in component that announces route changes to screen readers. Included by default in Nuxt 4.4+ app templates.useRouteAnnouncer: Composable to customize announcement text on navigation.npx nuxi module add @nuxtjs/a11y for additional compile-time and runtime accessibility auditing.useFetch or useAsyncData, not top-level $fetchapp/ directory (Nuxt 4 convention)development
Native Web UI structured renderer schemas for compose-block drafts, search-results cards, dataframe tables, chart-json charts, and diff output
tools
Unified search hub. Route any web/real-time/X lookup through a 4-tier escalation: built-in web search → cli-jaw browser CDP → progrok Grok OAuth → web-ai (Grok Expert / GPT Pro). Use for: search, 검색, web search, latest news, real-time info, X/Twitter, fact lookup, deep research.
development
UI/UX intent discovery, design vocabulary, product personalities, UX state patterns, typography line break judgment, favicon/product logo design, and logo trust section design. Use when user design direction is vague, when building onboarding/empty/error states, when setting up favicons or product logos, or when referencing a product aesthetic.
development
Canonical owner of module boundary rules, circular dependency detection/prevention, implicit coupling taxonomy, barrel/re-export discipline, and boundary-only defensive programming. Referenced by dev, dev-code-reviewer, dev-backend, dev-frontend stubs.