Skip to content

Nuxt development recipes for AI agents rest on three moves: pin the agent to Nuxt 4 documentation through the official Nuxt MCP server, because agents mix Nuxt 3 and unreleased Nuxt 5 APIs; write the Nuxt 4 conventions into the agent’s instruction file; and let nuxt typecheck, @nuxt/test-utils and nuxt build prove each change. The recipes target Nuxt 4.5.

This page is for developers who let Claude Code, Codex or Cursor build a full-stack Nuxt app, and for the tech lead who has to trust the result. The agent’s feature works on your machine, but it put the pages in pages/ instead of app/pages/, passed a Zod schema straight to readValidatedBody, and read document.cookie in a plugin that also runs on the server. The page works after client-side navigation, the hydration warnings scroll past, and the first user who opens a deep link directly gets a 500.

  • A context setup that keeps the agent on Nuxt 4 when both its training data (Nuxt 3) and the newest docs and skills (Nuxt 5) pull it elsewhere
  • The official Nuxt MCP server wired into all three tools, plus the experimental dev-server MCP module
  • Seven prompts for the Nuxt work agents most often get wrong: validated server routes, data fetching, sessions, hybrid rendering, Cloudflare Workers, Nuxt Content, and the test harness
  • A gate table that signs a change off without anyone reading every line, and a failure table with recovery steps

An agent writing Nuxt code draws on three sources that disagree. Its training data is mostly Nuxt 3, with pages/ at the root and data that defaults to null. The newest material describes Nuxt 5: Nitro v3, h3 v2, and server helpers imported from nuxt/server, which only arrives in Nuxt 4.6. Your package.json says 4.5. Every step below exists to make the third source win.

  1. Write the Nuxt 4 rules down where every tool finds them: in AGENTS.md for Codex, in CLAUDE.md for Claude Code (or a CLAUDE.md containing @AGENTS.md; from v2.1.277 Claude Code reads AGENTS.md when there is no CLAUDE.md), and in a project Rule for Cursor.

    ## Nuxt rules for this repo (Nuxt 4.5, nitropack 2, h3 1.x)
    - Vue code lives in app/ (app/pages, app/components, app/composables, app/middleware,
    app/plugins). server/, shared/, content/, public/ and nuxt.config.ts stay at the root.
    - Code used by both app and server goes in shared/utils or shared/types.
    - Look up APIs in the Nuxt 4.x docs (Nuxt MCP server, version 4.x). Never apply Nuxt 5
    guidance: no h3 v2 APIs, and no nuxt/server imports until nuxt >= 4.6.
    - createError takes { status, statusText } (statusCode/statusMessage are deprecated).
    - Never add h3 or nitropack to package.json; use the versions Nuxt brings.
    - readValidatedBody / getValidatedQuery take a function: readValidatedBody(event, Schema.parse).
    - useFetch/useAsyncData: data and error start as undefined; branch on status, not pending.
    - No browser globals (window, document, localStorage) in setup, plugins or middleware
    unless guarded by import.meta.client or inside onMounted.
    - Done means: npx nuxt typecheck, npx eslint ., npx vitest run and npx nuxt build pass.
  2. Connect the Nuxt MCP server (next section) and tell the agent to query it with the 4.x version filter. The server’s list-documentation-pages tool accepts 3.x, 4.x, 5.x or all, so an unfiltered lookup can return Nuxt 5 pages. The filter is not a version pin: the 4.x docs already describe Nuxt 4.6 features such as nuxt/server, so check the nuxt version in package.json before accepting code built on them.

  3. Check any Nuxt skill before you install it. The nuxt skill in antfu/skills states that it “is based on Nuxt 5.x (5.0.0-0), generated at 2026-09-25”. On a Nuxt 4.5 project it teaches nuxt/server imports and h3 v2, so leave it out until you upgrade. The nuxt-ui skill in nuxt/ui targets @nuxt/ui v4 and is safe to add if you use that library; see installing and managing skills.

  4. Put the stale patterns in front of the reviewer too. These are the APIs the agent reaches for first:

    Agent writesStatus on Nuxt 4.5Write instead
    pages/, components/, composables/ at the root of a new projectNuxt 3 layout; Nuxt 4 defaults srcDir to app/app/pages/ and so on; migrate an old app with npx codemod@latest nuxt/4/file-structure
    readValidatedBody(event, BodySchema)h3 1.x expects a validation functionreadValidatedBody(event, BodySchema.parse)
    if (data.value === null) or pending.value as the loading flagdata and error default to undefined in Nuxt 4status.value === 'pending' and data.value === undefined
    import { defineEventHandler } from 'nuxt/server'Arrives in Nuxt 4.6 (not exported by 4.5.x)The auto-imported defineEventHandler
    routeRules: { '/blog/**': { isr: 3600 } } on Cloudflare or Nodeisr reaches the CDN only on Netlify and Vercelswr: 3600 everywhere else
    preset: 'cloudflare-pages' for a new WorkerPages presetpreset: 'cloudflare_module', the preset Nitro recommends for Workers

Connect the agent to the Nuxt docs and your dev server

Section titled “Connect the agent to the Nuxt docs and your dev server”

The Nuxt team runs a documentation MCP server at https://nuxt.com/mcp over HTTP, with no authentication. Its tools list and fetch documentation pages, blog posts, deployment guides, modules (with README, compatibility and download stats) and the changelog. The X-MCP-Tools header limits which tools load, which keeps the context cost down; see reducing MCP token cost.

Terminal window
# Terminal, in the project root. -s project writes .mcp.json so the team shares it.
claude mcp add -s project --transport http nuxt https://nuxt.com/mcp \
-H "X-MCP-Tools: list-documentation-pages,get-documentation-page,get-module"

Run /mcp in a session to confirm nuxt is connected.

The docs server knows Nuxt; it does not know your app. For that, Anthony Fu’s nuxt-mcp-dev module (marked “Experimental. Use with caution.”) adds an MCP endpoint to your dev server at http://localhost:3000/__mcp/sse and, per its README, updates the MCP config of VS Code, Cursor, Windsurf and Claude Code for you. Add it with modules: ['nuxt-mcp-dev'] in nuxt.config.ts. The endpoint uses the SSE transport, which Claude Code still supports but has deprecated, so treat it as a convenience rather than a gate. For the browser’s view of a page, add Playwright MCP; the other dev-server servers are compared in framework devtools MCP servers.

Validate a server route with Zod and a session check

Section titled “Validate a server route with Zod and a session check”

Server routes are where the agent’s Nuxt 3 and Nuxt 5 habits collide. The route below needs a validated body, an authenticated user, and a proper status code for each failure.

The 400 on invalid input comes from h3 itself: when the validation function throws, readValidatedBody turns it into a 400. That is why passing the schema object is dangerous. The call fails on every request, and a test that only checks “some error” still passes.

Fetch data without duplicate requests or hydration errors

Section titled “Fetch data without duplicate requests or hydration errors”

The agent’s usual data layer is $fetch inside onMounted, which fetches twice (once on the server, once on the client) or not at all on the server. The Nuxt pattern is useFetch or useAsyncData in setup, with a stable key and the status ref.

The shared-key assertion matters. In Nuxt 4, components that call useAsyncData or useFetch with the same key share one data, error and status ref, and the docs require consistent options across those calls. A composable that builds keys from unstable values (a new object each render) breaks the sharing without breaking a type check.

Add sessions and route middleware without SSR leaks

Section titled “Add sessions and route middleware without SSR leaks”

Auth spans a server route, a route middleware, a plugin and a composable. The SSR boundary is where the agent fails: a plugin that reads document.cookie crashes the server render, and a middleware that trusts client state lets a crafted request through. nuxt-auth-utils keeps the session in a sealed cookie and gives you requireUserSession on the server and useUserSession in the app, which removes most of the hand-written token code.

Start in plan mode (/plan) and approve the file list before any code exists. After the change, run /code-review and ask it to list every file under server/api/ that does not call requireUserSession. For CI, run the same audit read-only: claude -p "…" --allowedTools "Read,Grep,Glob".

Marketing pages should be static, the dashboard rendered on the client or per request, and the blog cached. In Nuxt, that is one routeRules block, and the one fact the agent gets wrong is which rules your host honours.

On Vercel or Netlify, swap swr for isr and state the host in the prompt. Nitro maps route rules to those platforms’ native CDN rules, and nowhere else.

Deploy to Cloudflare Workers with D1 and KV

Section titled “Deploy to Cloudflare Workers with D1 and KV”

Nitro’s cloudflare_module preset builds a Workers module, and cloudflare.deployConfig: true generates the wrangler.json. Bindings reach your server code through event.context.cloudflare.env. The agent’s two classic mistakes are the Pages preset and a binding name collision with Nuxt Content, which uses a D1 binding named DB by default.

For the Workers platform itself (Queues, Durable Objects, limits), see serverless development patterns; for letting the agent inspect your Cloudflare account, see the Cloudflare MCP server. Drizzle schema and migration patterns are in ORM best practices.

Nuxt Content 3 replaced the v2 query API with collections declared in content.config.ts and queried with queryCollection(), backed by SQLite (D1 on Cloudflare). An agent trained on v2 writes queryContent() and <ContentDoc>, which no longer exist.

Set up the Nuxt test harness the agent runs every time

Section titled “Set up the Nuxt test harness the agent runs every time”

Tests only protect you if the agent runs them after every edit. @nuxt/test-utils 4.x splits the work into Vitest projects: plain unit tests in Node, Nuxt-runtime tests (components, composables, plugins) in the nuxt environment, and end-to-end tests that build and serve the app.

Add a Stop hook whose script runs npx nuxt typecheck && npx vitest run and exits with code 2 on failure. The error goes back to the agent instead of ending the turn. See hooks automation.

The deliberate failure at the end is the cheapest check that the tests can fail at all. An agent-written test that passes whatever the code does is worse than none.

How to verify agent-written Nuxt code without reading every line

Section titled “How to verify agent-written Nuxt code without reading every line”

Read the diffs of nuxt.config.ts, anything under app/middleware/ and app/plugins/, and every server route that reads a session. Let the gates prove the rest.

GateCommand or toolWhat goes red
Typesnpx nuxt typecheckWrong useFetch return types, a nuxt/server import on Nuxt 4.5, a shared type the client did not follow
Lintnpx eslint . with @nuxt/eslint 1.17.0Unused auto-imports, browser globals where you ban them with no-restricted-globals
Unit and runtime testsnpx vitest run --project unit --project nuxtComposable behaviour, component states, mocked endpoints
End to endnpx vitest run --project e2e, or Playwright against npx nuxt previewAuth bypass, status codes, cache headers, redirects
Buildnpx nuxt buildPrerender errors, Nuxt Content parse errors, preset problems
HydrationPlaywright test that fails on any console message containing HydrationServer and client markup that differ
Bundlenpx nuxt analyze (experimental)A dependency that doubled the client bundle

The developer who owns the pull request signs off on the gate results and the files named above; CI enforces the rest. For how that review scales across a team, see reviewing agent pull requests, and for writing the acceptance criteria your e2e tests encode, see acceptance criteria agents can verify.

SymptomCauseRecovery
Every POST to a new route returns 400readValidatedBody(event, Schema) with the schema objectPass Schema.parse; add a test that a valid body returns 2xx, not only that invalid ones fail
Pages 404 after the agent adds themFiles created in root pages/ while the app uses app/ (or the reverse)Move them under app/pages/; keep the directory rule in AGENTS.md
Cannot find module 'nuxt/server' or h3 errors about event.reqGuidance for Nuxt 4.6+ or Nuxt 5 (the 4.x docs already describe 4.6; the docs main branch and Nuxt 5 skills describe 5)Check package.json’s nuxt version before accepting nuxt/server imports; on 4.5, remove any direct h3 dependency and revert to auto-imports
document is not defined during SSRBrowser API in a plugin, middleware or setupGuard with import.meta.client, move it into onMounted, or name the plugin *.client.ts
Hydration mismatch warningsDate.now(), Math.random() or locale formatting in renderCompute on the server and pass it through useState, or wrap the widget in <ClientOnly>
A page shows another request’s dataTwo useFetch calls share a key with different optionsBuild keys from the full URL and query; keep options identical for a shared key
Blog pages never refresh after isr: trueWithout a TTL, isr: true keeps a page until the next deploy; without Netlify or Vercel, isr behaves like swr and gets no CDN cachingUse swr with a TTL; add the cache-header e2e test
D1 queries hit the wrong database after adding Nuxt ContentBoth use the DB bindingRename your app binding (for example APP_DB) and redeploy

Did this guide help you?

One tap, no sign-in.

not at all a lot