> nuxt
You are an expert in Nuxt 3, the full-stack Vue framework with server-side rendering, auto-imports, file-based routing, API routes powered by Nitro, and 200+ modules. You help developers build production Vue applications with hybrid rendering (SSR/SSG/SPA per route), server components, middleware, state management with useState, data fetching with useFetch/useAsyncData, and deployment to 20+ platforms.
curl "https://skillshub.wtf/TerminalSkills/skills/nuxt?format=md"Nuxt — The Vue Framework
You are an expert in Nuxt 3, the full-stack Vue framework with server-side rendering, auto-imports, file-based routing, API routes powered by Nitro, and 200+ modules. You help developers build production Vue applications with hybrid rendering (SSR/SSG/SPA per route), server components, middleware, state management with useState, data fetching with useFetch/useAsyncData, and deployment to 20+ platforms.
Core Capabilities
Pages and Routing
<!-- pages/index.vue — Auto-routed to / -->
<script setup lang="ts">
const { data: posts } = await useFetch('/api/posts')
</script>
<template>
<div>
<h1>Blog</h1>
<div v-for="post in posts" :key="post.id" class="post-card">
<NuxtLink :to="`/posts/${post.slug}`">
<h2>{{ post.title }}</h2>
<p>{{ post.excerpt }}</p>
</NuxtLink>
</div>
</div>
</template>
<!-- pages/posts/[slug].vue — Dynamic route -->
<script setup lang="ts">
const route = useRoute()
const { data: post, error } = await useAsyncData(
`post-${route.params.slug}`,
() => $fetch(`/api/posts/${route.params.slug}`)
)
if (error.value) {
throw createError({ statusCode: 404, message: 'Post not found' })
}
// SEO
useHead({
title: post.value?.title,
meta: [{ name: 'description', content: post.value?.excerpt }],
})
useSeoMeta({
ogTitle: post.value?.title,
ogImage: post.value?.coverImage,
})
</script>
<template>
<article v-if="post">
<h1>{{ post.title }}</h1>
<div v-html="post.content" />
</article>
</template>
Server API Routes
// server/api/posts/index.get.ts
export default defineEventHandler(async () => {
const posts = await db.posts.findMany({ orderBy: { createdAt: 'desc' } })
return posts
})
// server/api/posts/[slug].get.ts
export default defineEventHandler(async (event) => {
const slug = getRouterParam(event, 'slug')
const post = await db.posts.findUnique({ where: { slug } })
if (!post) throw createError({ statusCode: 404, message: 'Not found' })
return post
})
// server/api/posts/index.post.ts
export default defineEventHandler(async (event) => {
const body = await readBody(event)
const session = await requireAuth(event)
return db.posts.create({ data: { ...body, authorId: session.userId } })
})
// server/middleware/auth.ts
export default defineEventHandler(async (event) => {
const path = getRequestURL(event).pathname
if (!path.startsWith('/api/admin')) return
const session = await getSession(event)
if (!session) throw createError({ statusCode: 401 })
event.context.user = session.user
})
Composables and State
// composables/useAuth.ts — Auto-imported everywhere
export function useAuth() {
const user = useState<User | null>('user', () => null)
const isLoggedIn = computed(() => !!user.value)
async function login(email: string, password: string) {
user.value = await $fetch('/api/auth/login', { method: 'POST', body: { email, password } })
}
async function logout() {
await $fetch('/api/auth/logout', { method: 'POST' })
user.value = null
navigateTo('/login')
}
return { user, isLoggedIn, login, logout }
}
Installation
npx nuxi@latest init my-app
cd my-app && npm install
npm run dev
Best Practices
- Auto-imports — Components, composables, utils auto-imported; no import statements needed
- useFetch for data — SSR-safe data fetching; deduplicates requests, caches across navigation
- Hybrid rendering — Set per-route rendering in
nuxt.config.ts: SSR, SSG, SPA, or ISR - useState — SSR-safe reactive state; shared across components, serialized server→client
- Server routes —
server/api/directory; powered by Nitro; deploy to any platform - SEO —
useHead()anduseSeoMeta()for per-page meta tags; SSR-rendered for crawlers - Modules — 200+ modules:
@nuxtjs/tailwindcss,@sidebase/nuxt-auth,@nuxt/image, etc. - Nitro engine — Universal server deploys to Node, Vercel, Netlify, Cloudflare, Deno, Bun
> related_skills --same-repo
> zustand
You are an expert in Zustand, the small, fast, and scalable state management library for React. You help developers manage global state without boilerplate using Zustand's hook-based stores, selectors for performance, middleware (persist, devtools, immer), computed values, and async actions — replacing Redux complexity with a simple, un-opinionated API in under 1KB.
> zod
You are an expert in Zod, the TypeScript-first schema declaration and validation library. You help developers define schemas that validate data at runtime AND infer TypeScript types at compile time — eliminating the need to write types and validators separately. Used for API input validation, form validation, environment variables, config files, and any data boundary.
> xero-accounting
Integrate with the Xero accounting API to sync invoices, expenses, bank transactions, and contacts — and generate financial reports like P&L and balance sheet. Use when: connecting apps to Xero, automating bookkeeping workflows, syncing accounting data, or pulling financial reports programmatically.
> windsurf-rules
Configure Windsurf AI coding assistant with .windsurfrules and workspace rules. Use when: customizing Windsurf for a project, setting AI coding standards, creating team-shared Windsurf configurations, or tuning Cascade AI behavior.