AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
Nuxt is a full-stack Vue framework designed for universal deployment. This skill provides essential guidance on Nuxt 5, covering its directory structure, file-based routing, server-side rendering, and Nitro-based server engine. It includes best practices for data fetching, state management, and modular architecture, helping developers leverage features like auto-imports and hybrid rendering.
What it does
- Explains the Nuxt 5 directory structure and configuration conventions.
- Details file-based routing, including typed and case-sensitive routes.
- Provides guidance on data fetching using useFetch and $fetch.
- Covers server-side rendering, hybrid rendering, and Nitro server integration.
- Explains how to extend applications using Nuxt Layers and modules.
- Outlines lifecycle hooks for build-time and runtime customization.
When to use it
- When starting a new full-stack project with Vue and Nuxt.
- When migrating existing projects to Nuxt 5 and Nitro v3.
- When implementing server-side rendering or hybrid rendering strategies.
- When creating reusable application layers or custom Nuxt modules.
- When optimizing data fetching patterns and state management in SSR environments.
Advantages
- Provides standardized patterns for Nuxt 5 development.
- Simplifies complex concepts like Nitro server integration and lifecycle hooks.
- Offers clear guidance on project structure and file-based routing.
- Supports efficient code reuse through the Nuxt Layers system.
Usage examples
- “How do I structure my Nuxt 5 project directory?”
- The agent explains the default app/ directory structure for Vue code and the root-level placement for server/, public/, and nuxt.config.ts files.
- “Explain how to use layers to share components between projects.”
- The agent provides instructions on using the extends property in nuxt.config.ts to import layers from local directories, git repositories, or npm packages.
- “How do I hook into the page navigation lifecycle?”
- The agent shows how to use nuxtApp.hook('page:finish', ...) within a plugin to execute code after navigation completes.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/antfu/nuxt/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip nuxt.zip -d .agents/skills
Documentation by Anthony Fu
Nuxt is a full-stack Vue framework that provides server-side rendering, file-based routing, auto-imports, and a powerful module system. It uses Nitro as its server engine for universal deployment across Node.js, serverless, and edge platforms.
The skill is based on Nuxt 5.x (
5.0.0-0), generated at 2026-11-05.
Directory layout: the default
srcDirisapp/— Vue app code (app.vue,components/,composables/,pages/, etc.) lives underapp/, whileserver/,shared/,public/,modules/,layers/andnuxt.config.tsstay at the project root. The~/@aliases point atapp/; use~~/@@for the root.
Nuxt 5 note: Nuxt 5 makes many former experimental flags the default. The biggest shifts for agents: server code moves to Nitro v3 (h3 v2, Web-standard
Request/Response), server utilities import fromnuxt/serverand are no longer auto-imported by default,$fetch/useFetchare typed from generated route types, routing is case-sensitive and typed by default, and the bundler is Vite 8 (Rolldown). Nuxt 5 requires Node22.19/24.11+. A Nitro v2 compatibility layer (nitroLegacy) keeps older server code building during migration. See individual references for details.
Core
| Topic | Description | Reference |
|---|---|---|
| Directory Structure | Nuxt 4 app/ srcDir, shared/, aliases, conventions | core-directory-structure |
| Configuration | nuxt.config.ts, app.config.ts, aliases, Nuxt 5 defaults, jiti removal, experimental | core-config |
| CLI Commands | Dev server, build, generate, preview, and utility commands | core-cli |
| Routing | File-based routing, case-sensitive + typed routes, named views, layout props, middleware | core-routing |
| Data Fetching | useFetch, useAsyncData, $fetch, typed routes, createUseFetch factories, caching | core-data-fetching |
| Modules | Creating and using Nuxt modules, Nuxt Kit utilities | core-modules |
| Deployment | Platform-agnostic deployment with Nitro, Vercel, Netlify, Cloudflare | core-deployment |
Features
| Topic | Description | Reference |
|---|---|---|
| Composables Auto-imports | Vue/Nuxt composables, custom composables, shared/, useAnnouncer | features-composables |
| Components Auto-imports | Component naming, lazy loading, hydration strategies | features-components-autoimport |
| Built-in Components | NuxtLink, NuxtPage, NuxtLayout, NuxtAnnouncer, ClientOnly, and more | features-components |
| State Management | useState composable, SSR-friendly state, Pinia integration | features-state |
| Server Routes | API routes, nuxt/server imports, Nitro v3 (h3 v2), sessions, middleware | features-server |
Rendering
| Topic | Description | Reference |
|---|---|---|
| Rendering Modes | Universal (SSR), client-side (SPA), hybrid rendering, route rules | rendering-modes |
Best Practices
| Topic | Description | Reference |
|---|---|---|
| Data Fetching Patterns | Efficient fetching, caching, parallel requests, error handling | best-practices-data-fetching |
| SSR & Hydration | Avoiding context leaks, hydration mismatches, composable patterns | best-practices-ssr |
Advanced
| Topic | Description | Reference |
|---|---|---|
| Layers | Extending applications with reusable layers | advanced-layers |
| Lifecycle Hooks | Build-time, runtime, and server hooks | advanced-hooks |
| Module Authoring | Publishable modules with Nuxt Kit, keyed composables, dependencies | advanced-module-authoring |
Files
- ATTRIBUTION.mdAdded by AutoGineer889 B
- GENERATION.md134 B
- LICENSELicence file added by AutoGineer1.1 KiB
- SKILL.md4.5 KiB
- references/advanced-hooks.md7.2 KiB
- references/advanced-layers.md5.1 KiB
- references/advanced-module-authoring.md16.5 KiB
- references/best-practices-data-fetching.md9.2 KiB
- references/best-practices-ssr.md7.5 KiB
- references/core-cli.md4.8 KiB
- references/core-config.md10.5 KiB
- references/core-data-fetching.md11.4 KiB
- references/core-deployment.md5.1 KiB
- references/core-directory-structure.md9.8 KiB
- references/core-modules.md5.4 KiB
- references/core-routing.md6.8 KiB
- references/features-components-autoimport.md5.9 KiB
- references/features-components.md6.1 KiB
- references/features-composables.md7.2 KiB
- references/features-server.md11.1 KiB
- references/features-state.md3.9 KiB
- references/rendering-modes.md5.5 KiB
references/best-practices-ssr.md
name: ssr-best-practices description: Avoiding SSR context leaks, hydration mismatches, and proper composable usage
SSR Best Practices
Patterns for avoiding common SSR pitfalls: context leaks, hydration mismatches, and composable errors.
The "Nuxt Instance Unavailable" Error
This error occurs when calling Nuxt composables outside the proper context.
❌ Wrong: Composable Outside Setup
// composables/bad.ts
// Called at module level - no Nuxt context!
const config = useRuntimeConfig()
export function useMyComposable() {
return config.public.apiBase
}✅ Correct: Composable Inside Function
// composables/good.ts
export function useMyComposable() {
// Called inside the composable - has context
const config = useRuntimeConfig()
return config.public.apiBase
}Valid Contexts for Composables
Nuxt composables work in:
<script setup>blockssetup()functiondefineNuxtPlugin()callbacksdefineNuxtRouteMiddleware()callbacks
// ✅ Plugin
export default defineNuxtPlugin(() => {
const config = useRuntimeConfig() // Works
})
// ✅ Middleware
export default defineNuxtRouteMiddleware(() => {
const route = useRoute() // Works
})Avoid State Leaks Between Requests
❌ Wrong: Module-level State
// composables/bad.ts
// This state is SHARED between all requests on server!
const globalState = ref({ user: null })
export function useUser() {
return globalState
}✅ Correct: Use useState
// composables/good.ts
export function useUser() {
// useState creates request-isolated state
return useState('user', () => ({ user: null }))
}Why This Matters
On the server, module-level state persists across requests, causing:
Data leaking between users
Security vulnerabilities
Memory leaks
Hydration Mismatch Prevention
Hydration mismatches occur when server HTML differs from client render.
❌ Wrong: Browser APIs in Setup
<script setup>
// localStorage doesn't exist on server!
const theme = localStorage.getItem('theme') || 'light'
</script>✅ Correct: Use SSR-safe Alternatives
<script setup>
// useCookie works on both server and client
const theme = useCookie('theme', { default: () => 'light' })
</script>❌ Wrong: Random/Time-based Values
<template>
<div>{{ Math.random() }}</div>
<div>{{ new Date().toLocaleTimeString() }}</div>
</template>✅ Correct: Use useState for Consistency
<script setup>
// Value is generated once on server, hydrated on client
const randomValue = useState('random', () => Math.random())
</script>
<template>
<div>{{ randomValue }}</div>
</template>❌ Wrong: Conditional Rendering on Client State
<template>
<!-- window doesn't exist on server -->
<div v-if="window?.innerWidth > 768">Desktop</div>
</template>✅ Correct: Use CSS or ClientOnly
<template>
<!-- CSS media queries work on both -->
<div class="hidden md:block">Desktop</div>
<div class="md:hidden">Mobile</div>
<!-- Or use ClientOnly for JS-dependent rendering -->
<ClientOnly>
<ResponsiveComponent />
<template #fallback>Loading...</template>
</ClientOnly>
</template>iOS Safari Phone Numbers
iOS Safari auto-links phone numbers, dates, addresses and emails before hydration, causing iOS-only mismatches. Disable with app.head.meta: [{ name: 'format-detection', content: 'telephone=no, date=no, email=no, address=no' }], and wrap numbers that should stay tappable in <a href="tel:...">.
Browser-only Code
Use import.meta.client
<script setup>
if (import.meta.client) {
// Only runs in browser
window.addEventListener('scroll', handleScroll)
}
</script>Use onMounted for DOM Access
<script setup>
const el = ref<HTMLElement>()
onMounted(() => {
// Safe - only runs on client after hydration
el.value?.focus()
initThirdPartyLib()
})
</script>Dynamic Imports for Browser Libraries
<script setup>
onMounted(async () => {
const { Chart } = await import('chart.js')
new Chart(canvas.value, config)
})
</script>Server-only Code
Use import.meta.server
<script setup>
if (import.meta.server) {
// Only runs on server
const secrets = useRuntimeConfig().apiSecret
}
</script>Server Components
<!-- components/ServerData.server.vue -->
<script setup>
// This entire component only runs on server
const data = await fetchSensitiveData()
</script>
<template>
<div>{{ data }}</div>
</template>Async Composable Patterns
❌ Wrong: Await Before Composable
<script setup>
await someAsyncOperation()
const route = useRoute() // May fail - context lost after await
</script>✅ Correct: Get Context First
<script setup>
// Get all composables before any await
const route = useRoute()
const config = useRuntimeConfig()
await someAsyncOperation()
// Now safe to use route and config
</script>Plugin Best Practices
Client-only Plugins
// plugins/analytics.client.ts
export default defineNuxtPlugin(() => {
// Only runs on client
initAnalytics()
})Server-only Plugins
// plugins/server-init.server.ts
export default defineNuxtPlugin(() => {
// Only runs on server
initServerConnections()
})Provide/Inject Pattern
// plugins/api.ts
export default defineNuxtPlugin(() => {
const api = createApiClient()
return {
provide: {
api,
},
}
})<script setup>
const { $api } = useNuxtApp()
const data = await $api.get('/users')
</script>Third-party Library Integration
❌ Wrong: Import at Top Level
<script setup>
import SomeLibrary from 'browser-only-lib' // Breaks SSR
</script>✅ Correct: Dynamic Import
<script setup>
let library: typeof import('browser-only-lib')
onMounted(async () => {
library = await import('browser-only-lib')
library.init()
})
</script>Use ClientOnly Component
<template>
<ClientOnly>
<BrowserOnlyComponent />
<template #fallback>
<div class="skeleton">Loading...</div>
</template>
</ClientOnly>
</template>Resource Hints and Deferred Work
Nuxt emits preload/modulepreload for chunks the page needs and prefetch for lazily imported chunks, rendered as data-href and activated after onNuxtReady (experimental.deferPrefetchHints: false to prefetch immediately). To stop a chunk group being prefetched (e.g. signed-in-app chunks on a public prerendered page), set chunk.prefetch = false per entry in the build:manifest hook. Defer non-critical client work with onNuxtReady(() => import('big-lib'), { timeout: 2000 }).
Debugging SSR Issues
Check Rendering Context
<script setup>
console.log('Server:', import.meta.server)
console.log('Client:', import.meta.client)
</script>Use Nuxt DevTools
DevTools shows payload data and hydration state.
Common Error Messages
| Error | Cause |
|---|---|
| "Nuxt instance unavailable" | Composable called outside setup context |
| "Hydration mismatch" | Server/client HTML differs |
| "window is not defined" | Browser API used during SSR |
| "document is not defined" | DOM access during SSR |
<!-- Source references: - https://nuxt.com/docs/guide/concepts/auto-imports#vue-and-nuxt-composables - https://nuxt.com/docs/guide/best-practices/hydration - https://nuxt.com/docs/guide/best-practices/performance - https://nuxt.com/docs/getting-started/state-management#best-practices -->
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
What our scanner noticed· Low risk
- Instructions that use the network
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- Anthony Fu
- Publisher
- Anthony Fu (Community)
- Source
- antfu/skills · skills/nuxt · commit f63e9ec
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE.md)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Anthony Fu.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download nuxt.zip