Index of every page on this site: llms.txt
All skills
antfu avatar

/nuxt

@7de210b official
by Anthony Fuantfu/skills6k stars
342
Run it yourself

Nuxt full-stack Vue framework with SSR, auto-imports, and file-based routing. Use when working with Nuxt apps, server routes, useFetch, middleware, or hybrid rendering.

Use this Skill: https://skilld.dev/gh/antfu/skills/nuxt

Nothing lands on disk. Nothing to clean up.

Fork this Skill

Edit a local copy. It keeps the author and licence.

referencesbest-practices-ssr.md

≈1.7k tokens on demand. Your agent reads this file only when SKILL.md points to it.

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> blocks
  • setup() function
  • defineNuxtPlugin() callbacks
  • defineNuxtRouteMiddleware() 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>

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>

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/getting-started/state-management#best-practices -->

Source: SKILL.md on GitHub

No rule matched.

skilld matched fixed text patterns in SKILL.md and file names. Patterns miss obfuscated code.

skilld run checks every file with the same patterns. It asks for approval before it loads a Skill with a behavior marked Needs approval.

No alerts3d5 checks · Risk SAFE
  • Gen Agent Trust Hub3d

    This skill is a collection of documentation and reference materials for the Nuxt framework (version 5). It contains technical guides on routing, configuration, data fetching, and deployment, intended to assist an AI agent in working with Nuxt projects. No security risks were identified.

  • Socket3d

    No alerts

  • Snyk3d

    Risk: LOW · No issues

  • Runlayer8mo

    3/20 files flagged

  • ZeroLeaks6mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 7de210b. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub last week.

Activeupdated last month
Other metadata
metadata
{
  "author": "Anthony Fu",
  "version": "2026.9.25",
  "source": "Generated from https://github.com/nuxt/nuxt, scripts located at https://github.com/antfu/skills"
}
  • Nuxt
  • Vue
  • ssr
  • full-stack
  • file-based-routing
  • nitro
  • auto-imports
  • server-routes
  • composables
  • state-management

README badge

README badge for antfu/skills/nuxt

This skill provides comprehensive guidance on Nuxt 3, a full-stack Vue framework with server-side rendering, file-based routing, auto-imports, and Nitro-powered server deployment. It covers directory structure, configuration, routing, data fetching, state management, server routes, rendering modes, and module authoring across core, feature, and advanced sections.

Generated from the current SKILL.md.

Does this skill cover Nuxt 2?
No. This skill is based on Nuxt 3.x, generated at 2026-01-28.
What server runtime does Nuxt use?
Nuxt uses Nitro as its server engine, which supports universal deployment across Node.js, serverless, and edge platforms.
Does this skill cover server routes and API endpoints?
Yes. The skill includes guidance on server routes, API routes, server middleware, and the Nitro server engine.
What rendering modes are supported?
The skill covers universal (SSR), client-side (SPA), hybrid rendering, and route rules for controlling how pages are rendered.
Does this skill explain state management?
Yes. It covers the useState composable, SSR-friendly state patterns, and Pinia integration.

Generated from the current SKILL.md. These answers refresh after source changes.