# Nuxt

> This skill should be used when the user asks to "build a Nuxt app", "optimize Nuxt performance", "configure Nuxt rendering", "follow Nuxt best practices", or needs guidance on Nuxt 4 development patterns, hybrid rendering, or Core Web Vitals optimization.

- Skill: `the-perfect-developer/nuxt` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add the-perfect-developer/nuxt`
- Raw SKILL.md: https://api.skillmd.com/api/skills/the-perfect-developer/nuxt/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: the-perfect-developer (https://skillmd.com/u/the-perfect-developer)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/the-perfect-developer/nuxt

---


# Nuxt Best Practices

Guidance for building high-performance Nuxt 4 applications following official best practices. Covers rendering strategies, performance optimization, data fetching, component patterns, and profiling.

## Rendering Strategies

### Choose the Right Rendering Mode per Route

Nuxt 4 supports hybrid rendering via `routeRules`. Assign rendering strategies per route rather than using a single global mode:

```ts
// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    '/': { prerender: true },          // Static at build time
    '/products/**': { swr: 3600 },     // Cached, revalidated in background
    '/blog': { isr: 3600 },            // CDN-cached, revalidated hourly
    '/admin/**': { ssr: false },        // Client-side only
    '/api/**': { cors: true },
  },
})
```

**Route rule reference:**
- `prerender: true` — generate at build time, serve as static asset
- `swr: N` — server/proxy cache for N seconds, stale-while-revalidate
- `isr: N` — CDN cache until next deploy (Vercel/Netlify); `isr: true` means persist indefinitely
- `ssr: false` — browser-only rendering (SPA mode for that route)
- `redirect: '/new'` — server-side redirect
- `headers: {}` — add custom response headers (e.g., long cache on assets)

### Default to Universal Rendering

Universal rendering (SSR + hydration) is the default and best choice for content-oriented apps (blogs, e-commerce, marketing sites). It delivers:
- Immediate HTML visible to users and crawlers
- Full interactivity after hydration
- Better Core Web Vitals scores (LCP, CLS)

### Edge-Side Rendering

Deploy to CDN edge servers (Cloudflare Workers, Vercel Edge, Netlify Edge) for reduced latency. Nuxt's Nitro engine supports these out of the box — no code changes required, only a different build preset.

See `references/rendering.md` for a full breakdown of trade-offs and deployment targets.

## Component Best Practices

### Lazy-Load Non-Critical Components

Prefix any component with `Lazy` to defer its JavaScript until needed. This directly reduces initial bundle size and improves Time to Interactive (TTI):

```html
<script setup lang="ts">
const show = ref(false)
</script>

<template>
  <div>
    <button @click="show = true">Load list</button>
    <LazyMountainsList v-if="show" />
  </div>
</template>
```

### Use Lazy Hydration (Nuxt 3.16+)

Defer hydration of components until they enter the viewport or the browser is idle. This improves TTI without sacrificing SSR-rendered content:

```html
<template>
  <!-- Hydrate only when scrolled into view -->
  <LazyCommentSection hydrate-on-visible />

  <!-- Hydrate when browser is idle -->
  <LazyAnalyticsWidget hydrate-on-idle />

  <!-- Hydrate on user interaction -->
  <LazyChatWidget hydrate-on-interaction />
</template>
```

### Avoid Overusing Plugins

Plugins execute during the hydration phase and block interactivity. Audit plugins regularly — if logic does not need to run globally at startup, move it to a composable or utility function instead.

## Data Fetching

### Use `useFetch` and `useAsyncData`

These composables deduplicate server-side fetches. Data fetched on the server is serialized into the page payload and reused by the client — no double fetch:

```ts
// Good: data transferred via payload, no duplicate network request
const { data } = await useFetch('/api/products')

// Bad: runs separately on server and client
const data = await $fetch('/api/products')
```

### Keep Composables Synchronous at the Top Level

Vue and Nuxt composables rely on a synchronous lifecycle context. Do not call composables after an `await` outside of `<script setup>`, `defineNuxtComponent`, `defineNuxtPlugin`, or `defineNuxtRouteMiddleware`:

```ts
// Bad
const data = await someAsyncOperation()
const config = useRuntimeConfig() // context lost

// Good — call composable before await, or inside <script setup>
const config = useRuntimeConfig()
const data = await someAsyncOperation()
```

## Performance Optimization

### Images: Use `<NuxtImg>`

Replace all `<img>` tags with `<NuxtImg>` (requires `@nuxt/image`). It auto-converts to WebP/Avif, resizes, and generates responsive `sizes`:

```html
<!-- Above-the-fold / LCP image -->
<NuxtImg
  src="/hero.jpg"
  format="webp"
  preload
  loading="eager"
  fetch-priority="high"
  width="1200"
  height="600"
/>

<!-- Below-the-fold image -->
<NuxtImg
  src="/feature.jpg"
  format="webp"
  loading="lazy"
  fetch-priority="low"
  width="600"
  height="400"
/>
```

Always set `width` and `height` to prevent layout shift (CLS).

### Fonts: Use Nuxt Fonts

Add `@nuxt/fonts` to automatically self-host fonts, inject `@font-face` rules, and generate fallback metrics that minimize CLS. No manual `<link rel="preload">` required.

### Third-Party Scripts: Use Nuxt Scripts

Add `@nuxt/scripts` to load analytics, embeds, and social widgets without blocking the main thread. Scripts support deferred triggers and typed proxies:

```ts
const { proxy } = useScriptGoogleAnalytics({
  id: 'G-XXXXXXXX',
  scriptOptions: { trigger: 'manual' },
})
// Safe to call before script loads — events are queued
proxy.gtag('event', 'page_view')
```

### Leverage Smart Prefetching via `<NuxtLink>`

`<NuxtLink>` automatically prefetches JavaScript for in-viewport links. To reduce bandwidth on large sites, switch to interaction-based prefetching:

```ts
// nuxt.config.ts
export default defineNuxtConfig({
  experimental: {
    defaults: {
      nuxtLink: { prefetchOn: 'interaction' },
    },
  },
})
```

### Apply Vue-Level Optimizations

Nuxt apps are Vue apps — apply Vue performance primitives:
- `shallowRef` / `shallowReactive` for large objects not needing deep reactivity
- `v-once` for static subtrees that never change
- `v-memo` to skip re-renders when dependencies are unchanged
- `computed` to cache derived state rather than recalculating in templates

## Auto-Imports

Nuxt auto-imports components from `app/components/`, composables from `app/composables/`, and utilities from `app/utils/`. Only used exports appear in the production bundle — no manual tree-shaking needed.

Place server-only utilities in `server/utils/` — they are also auto-imported within the `server/` directory.

To make imports explicit (useful for clarity or monorepos), use the `#imports` alias:

```ts
import { ref, computed, useFetch } from '#imports'
```

## Common Pitfalls

| Problem | Solution |
|---|---|
| Double data fetch (server + client) | Use `useFetch` / `useAsyncData` instead of raw `$fetch` |
| Plugins blocking hydration | Move non-global logic to composables |
| Large bundles | Run `nuxi analyze`; lazy-load large components |
| Layout shift from images | Always set `width`/`height` on `<NuxtImg>` |
| Unoptimized fonts | Add `@nuxt/fonts` |
| INP degradation from third-party scripts | Add `@nuxt/scripts` with deferred triggers |
| Deep reactivity on large objects | Use `shallowRef` / `shallowReactive` |
| Composable called after `await` | Call composables synchronously before async operations |
| Unused dependencies bloating bundle | Audit `package.json`; remove unused packages |

## Profiling Workflow

1. **Bundle analysis** — `npx nuxi analyze` generates a visual treemap; identify large dependencies.
2. **Nuxt DevTools** — Timeline, Render Tree, and Inspect tabs reveal component render costs and file sizes.
3. **Chrome DevTools** — Performance panel shows LCP/CLS live; Lighthouse gives actionable scores.
4. **PageSpeed Insights** — Combine lab + real-world field data for production auditing.
5. **WebPageTest** — Test from multiple global regions and network conditions.

## Additional Resources

### Reference Files

- **`references/performance.md`** — Detailed breakdown of all performance techniques, `routeRules` options, and Core Web Vitals targets
- **`references/rendering.md`** — In-depth rendering mode trade-offs, hydration mismatch prevention, and deployment targets

