Everything-claude-code nuxt4-patterns
Nuxt 4 app patterns for hydration safety, performance, route rules, lazy loading, and SSR-safe data fetching with useFetch and useAsyncData.
install
source · Clone the upstream repo
git clone https://github.com/affaan-m/everything-claude-code
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/affaan-m/everything-claude-code "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/nuxt4-patterns" ~/.claude/skills/affaan-m-everything-claude-code-nuxt4-patterns-a5282f && rm -rf "$T"
manifest:
skills/nuxt4-patterns/SKILL.mdsource content
Nuxt 4 Patterns
Use when building or debugging Nuxt 4 apps with SSR, hybrid rendering, route rules, or page-level data fetching.
When to Activate
- Hydration mismatches between server HTML and client state
- Route-level rendering decisions such as prerender, SWR, ISR, or client-only sections
- Performance work around lazy loading, lazy hydration, or payload size
- Page or component data fetching with
,useFetch
, oruseAsyncData$fetch - Nuxt routing issues tied to route params, middleware, or SSR/client differences
Hydration Safety
- Keep the first render deterministic. Do not put
,Date.now()
, browser-only APIs, or storage reads directly into SSR-rendered template state.Math.random() - Move browser-only logic behind
,onMounted()
,import.meta.client
, or aClientOnly
component when the server cannot produce the same markup..client.vue - Use Nuxt's
composable, not the one fromuseRoute()
.vue-router - Do not use
to drive SSR-rendered markup. URL fragments are client-only, which can create hydration mismatches.route.fullPath - Treat
as an escape hatch for truly browser-only areas, not a default fix for mismatches.ssr: false
Data Fetching
- Prefer
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.await useFetch() - Use
when the fetcher is not a simpleuseAsyncData()
call, when you need a custom key, or when you are composing multiple async sources.$fetch() - Give
a stable key for cache reuse and predictable refresh behavior.useAsyncData() - Keep
handlers side-effect free. They can run during SSR and hydration.useAsyncData() - Use
for user-triggered writes or client-only actions, not top-level page data that should be hydrated from SSR.$fetch() - Use
,lazy: true
, oruseLazyFetch()
for non-critical data that should not block navigation. HandleuseLazyAsyncData()
in the UI.status === 'pending' - Use
only for data that is not needed for SEO or the first paint.server: false - Trim payload size with
and prefer shallower payloads when deep reactivity is unnecessary.pick
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, })
Route Rules
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 } }, }, })
: static HTML at build timeprerender
: serve cached content and revalidate in the backgroundswr
: incremental static regeneration on supported platformsisr
: client-rendered routessr: false
orcache
: Nitro-level response behaviorredirect
Pick route rules per route group, not globally. Marketing pages, catalogs, dashboards, and APIs usually need different strategies.
Lazy Loading and Performance
- Nuxt already code-splits pages by route. Keep route boundaries meaningful before micro-optimizing component splits.
- Use the
prefix to dynamically import non-critical components.Lazy - Conditionally render lazy components with
so the chunk is not loaded until the UI actually needs it.v-if - Use lazy hydration for below-the-fold or non-critical interactive UI.
<template> <LazyRecommendations v-if="showRecommendations" /> <LazyProductGallery hydrate-on-visible /> </template>
- For custom strategies, use
with a visibility or idle strategy.defineLazyHydrationComponent() - Nuxt lazy hydration works on single-file components. Passing new props to a lazily hydrated component will trigger hydration immediately.
- Use
for internal navigation so Nuxt can prefetch route components and generated payloads.NuxtLink
Review Checklist
- First SSR render and hydrated client render produce the same markup
- Page data uses
oruseFetch
, not top-leveluseAsyncData$fetch - Non-critical data is lazy and has explicit loading UI
- Route rules match the page's SEO and freshness requirements
- Heavy interactive islands are lazy-loaded or lazily hydrated