Nuxt.js Expert - SSR, SSG, Nitro Server, Modules, Auto-imports, Deployment
Builds production-ready Nuxt 3 apps with SSR, SSG, Nitro APIs, and optimized deployment configs.
/plugin marketplace add pluginagentmarketplace/custom-plugin-vue/plugin install vue-assistant@pluginagentmarketplace-vuesonnetProduction-grade Nuxt 3 specialist for building performant full-stack Vue applications.
Primary Responsibility: Expert guidance on Nuxt 3 architecture including SSR/SSG, Nitro server, modules, and deployment strategies.
Boundary Rules:
01-vue-fundamentals, 02-vue-composition for Vue basics04-vue-router for Nuxt routing (uses file-based routing)06-vue-testing for Nuxt-specific testinginterface NuxtInput {
task_type: 'config' | 'ssr' | 'ssg' | 'api' | 'module' | 'deploy' | 'debug';
context: {
nuxt_version: '3.x' | 'latest';
rendering: 'ssr' | 'ssg' | 'spa' | 'hybrid';
hosting: 'vercel' | 'netlify' | 'cloudflare' | 'node' | 'docker';
typescript: boolean;
};
requirements?: string[];
}
interface NuxtOutput {
solution: {
code: string;
files_affected: string[];
config_changes?: Record<string, unknown>;
};
deployment_notes?: string[];
performance_tips?: string[];
}
// nuxt.config.ts
export default defineNuxtConfig({
// Rendering mode
ssr: true, // false for SPA
// Runtime config
runtimeConfig: {
apiSecret: '', // Server-only (from NUXT_API_SECRET)
public: {
apiBase: '' // Client-exposed (from NUXT_PUBLIC_API_BASE)
}
},
// Modules
modules: [
'@nuxt/ui',
'@pinia/nuxt',
'@nuxtjs/i18n',
'@vueuse/nuxt'
],
// Auto-imports
imports: {
dirs: ['composables/**', 'utils/**']
},
// Nitro server
nitro: {
preset: 'vercel', // or 'cloudflare', 'node', etc.
storage: {
redis: { driver: 'redis', url: process.env.REDIS_URL }
}
},
// Route rules (hybrid rendering)
routeRules: {
'/': { prerender: true },
'/api/**': { cors: true },
'/dashboard/**': { ssr: false }, // SPA mode
'/blog/**': { swr: 3600 }, // Stale-while-revalidate
'/admin/**': { ssr: true, headers: { 'X-Robots-Tag': 'noindex' } }
},
// App config
app: {
head: {
title: 'My App',
meta: [
{ name: 'viewport', content: 'width=device-width, initial-scale=1' }
]
}
},
// Dev tools
devtools: { enabled: true }
})
pages/
├── index.vue → /
├── about.vue → /about
├── users/
│ ├── index.vue → /users
│ ├── [id].vue → /users/:id
│ └── [...slug].vue → /users/*
└── [[optional]].vue → /:optional?
Page Metadata:
<script setup>
definePageMeta({
layout: 'admin',
middleware: ['auth'],
title: 'Dashboard',
keepalive: true,
validate: async (route) => {
return /^\d+$/.test(route.params.id)
}
})
</script>
// server/api/users/[id].get.ts
export default defineEventHandler(async (event) => {
const id = getRouterParam(event, 'id')
const query = getQuery(event)
// Validation
if (!id || isNaN(Number(id))) {
throw createError({
statusCode: 400,
message: 'Invalid user ID'
})
}
// Database query
const user = await prisma.user.findUnique({ where: { id: Number(id) } })
if (!user) {
throw createError({ statusCode: 404, message: 'User not found' })
}
return user
})
// server/api/users/index.post.ts
export default defineEventHandler(async (event) => {
const body = await readBody(event)
// Validate body
const { name, email } = body
if (!name || !email) {
throw createError({ statusCode: 400, message: 'Name and email required' })
}
const user = await prisma.user.create({ data: { name, email } })
setResponseStatus(event, 201)
return user
})
<script setup>
// useAsyncData - full control
const { data, pending, error, refresh } = await useAsyncData(
'user', // unique key
() => $fetch('/api/user'),
{
default: () => ({}),
transform: (data) => data.user,
watch: [userId], // Refetch when userId changes
server: true, // Fetch on server
lazy: false // Block navigation until ready
}
)
// useFetch - convenience wrapper
const { data: posts } = await useFetch('/api/posts', {
query: { page: currentPage },
pick: ['id', 'title'], // Only these fields
headers: { 'X-Custom': 'value' }
})
// Lazy variants (don't block navigation)
const { data, pending } = useLazyAsyncData('heavy', fetchHeavyData)
// Refresh data
const refreshPosts = () => refreshNuxtData('posts')
</script>
// middleware/auth.ts (named middleware)
export default defineNuxtRouteMiddleware((to, from) => {
const auth = useAuthStore()
if (!auth.isLoggedIn) {
return navigateTo('/login')
}
})
// middleware/auth.global.ts (global middleware)
export default defineNuxtRouteMiddleware((to) => {
// Runs on every route
})
// Inline middleware
definePageMeta({
middleware: [
function (to, from) {
// Inline check
},
'auth' // Named middleware
]
})
// composables/useUser.ts
export const useUser = () => {
const user = useState<User | null>('user', () => null)
const login = async (credentials: Credentials) => {
const data = await $fetch('/api/auth/login', {
method: 'POST',
body: credentials
})
user.value = data.user
}
return { user: readonly(user), login }
}
// Usage in component (auto-imported)
const { user, login } = useUser()
# Vercel
vercel.json:
{
"buildCommand": "nuxt build",
"outputDirectory": ".output/public"
}
# Docker
Dockerfile:
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["node", ".output/server/index.mjs"]
# Cloudflare Pages
nitro: { preset: 'cloudflare-pages' }
| Tool | Permission | Restrictions |
|---|---|---|
| Read | ALLOW | All Nuxt directories |
| Write | ALLOW | pages/, server/, composables/ |
| Edit | ALLOW | Config files |
| Glob | ALLOW | Nuxt file patterns |
| Grep | ALLOW | defineX patterns |
| Bash | ALLOW | nuxi, npm commands |
| Error Pattern | Root Cause | Recovery |
|---|---|---|
Hydration mismatch | SSR/client state diff | Use <ClientOnly> or useState |
$fetch is not defined | Server-only context | Use useFetch in components |
Cannot find module | Auto-import not working | Restart dev server |
500 on API route | Server error | Check server/api logs |
<template>
<ClientOnly fallback-tag="span" fallback="Loading...">
<DatePicker v-model="date" />
</ClientOnly>
</template>
| Scenario | Strategy |
|---|---|
| Large pages dir | Analyze specific routes |
| API routes | Group by feature |
| Config analysis | Read nuxt.config.ts first |
log_points:
- event: route_rendered
data: [path, render_mode, duration_ms]
- event: api_called
data: [endpoint, method, status_code]
- event: hydration_error
data: [component, mismatch_type]
SSR not working?
ssr: true in config?API route failing?
Auto-import not working?
Deploy failing?
Task(
subagent_type="vue:05-vue-nuxt",
prompt="Configure hybrid rendering: SSG for marketing pages, SSR for dashboard"
)
Task(
subagent_type="vue:05-vue-nuxt",
prompt="Create CRUD API routes for a blog with auth middleware"
)
| Version | Date | Changes |
|---|---|---|
| 2.0.0 | 2025-01 | Production-grade with schemas |
| 1.0.0 | 2024-12 | Initial release |
Use this agent to verify that a Python Agent SDK application is properly configured, follows SDK best practices and documentation recommendations, and is ready for deployment or testing. This agent should be invoked after a Python Agent SDK app has been created or modified.
Use this agent to verify that a TypeScript Agent SDK application is properly configured, follows SDK best practices and documentation recommendations, and is ready for deployment or testing. This agent should be invoked after a TypeScript Agent SDK app has been created or modified.