Complete AI prompt library for Vue 3 and Nuxt 4 developers. Covers Composition API, Pinia state management, Nuxt server routes, authentication, component design, testing with Vitest and Playwright, and Vercel/Netlify deployment.
Vue 3 & Nuxt 4 in 2026: The Progressive Framework at Scale
Vue 3's Composition API and Nuxt 4's hybrid rendering make them a powerful pair for everything from marketing sites to complex dashboards. The key to getting great AI-generated Vue code is specifying the modern patterns: script setup, TypeScript, Pinia, and composables — not the Options API and Vuex patterns that dominate older tutorials.
AI + Vue 3: Breaking the Options API Default
The biggest quality gap in AI-generated Vue code is the Composition API vs Options API split. Most training data contains Options API code — it was the dominant Vue pattern for its first five years. Without explicit instruction, models default to it even in projects that have never used it. The practical fix is a standing session prompt: "Use <script setup> with TypeScript, defineProps<T> with generic types, Vue 3.4+ defineModel() for two-way binding, Pinia stores (not Vuex), and composables in composables/use*.ts — never Options API."
A subtler gap appears with Nuxt 4's server routes. Because Nuxt 4 is relatively new in most training datasets, models generate plausible-looking server route code using the wrong H3 event handler signatures, missing useRuntimeConfig() or incorrectly placing environment variable reads. The reliable fix: paste one working server/api/ route from your project as context before asking for a new one. The model then mirrors your established pattern instead of guessing from sparse training data.
For a cross-framework model comparison covering Vue alongside Django and GraphQL, see the Frontend & API Layer AI Prompts guide.
1. Nuxt 4 Project Architecture
You are a senior Nuxt 4 architect.
Design a production Nuxt 4 SaaS application structure:
- Authentication: nuxt-auth-utils with Google + GitHub providers
- Database: Drizzle ORM + PostgreSQL (Neon serverless)
- State: Pinia with pinia-plugin-persistedstate
- UI: Nuxt UI v3 (built on Tailwind CSS v4)
- Payments: Stripe with Nuxt server routes for webhooks
Deliver:
1. Full directory tree: pages/, components/, composables/, server/api/, stores/, types/
2. Which pages use SSR, SSG, or SPA mode (nuxtRouteRules per route)
3. Pinia store architecture: which stores, what they own, what they share
4. Server route security pattern: authentication middleware reused across all /api/* routes
5. nuxt.config.ts with runtime config strategy (public vs private env vars)
2. Vue 3 Components with script setup
You are a Vue 3 expert using the Composition API and script setup syntax.
Build a DataTable<T> generic Vue 3 component with TypeScript:
Features:
- Generic columns: ColumnDef<T> with key, label, sortable, width, renderCell slot
- Client-side sorting with visual direction indicators
- Row selection: checkbox per row, shift+click range, select-all header checkbox
- Pagination: configurable page sizes, emit page-change event for server-side support
- Slot: #actions(row) for per-row action buttons
- Loading state: skeleton rows (animated pulse)
- Empty state: default slot with override
- WCAG 2.1 AA: role="grid", aria-sort on sortable headers, keyboard navigation
Props interface with defineProps<Props>() TypeScript generic.
Emits: sort-change, page-change, selection-change.
CSS: scoped styles using Tailwind CSS utility classes.
No third-party table library dependencies.
3. Pinia Store with Optimistic Updates
You are a Pinia expert for Vue 3 TypeScript applications.
Build a useTaskStore (Setup store syntax) for a project management app:
State:
- tasks: Map<string, Task> (keyed by ID for O(1) lookup)
- tasksByProject: Map<string, string[]> (project ID → task IDs)
- loading: Record<string, boolean> (keyed by operation)
- error: string | null
- pagination: { page, pageSize, total, hasMore }
- filters: { status, priority, assignedTo, dueDateRange }
Actions:
- fetchTasks(projectId, filters): load paginated tasks into Map
- createTask(data): optimistic insert → API call → rollback on failure
- updateTask(id, patch): optimistic update → API call → rollback on failure
- deleteTask(id): optimistic remove → API call → restore on failure
Getters (computed):
- getTask(id): single task from Map
- projectTasks(projectId): ordered task array from tasksByProject Map
- overdueTasks: filtered derived list
- completionStats: { total, done, percentage } for current project
Persist: filters and pagination preferences only (not task data).
TypeScript throughout. Show usage in a Vue component.
4. Nuxt Server API Route with Validation
You are a Nuxt 4 server-side expert.
Build Nuxt server routes for the Task resource (server/api/tasks/):
Files: index.get.ts, index.post.ts, [id].get.ts, [id].patch.ts, [id].delete.ts
Every route must:
- Authenticate via requireUserSession() (nuxt-auth-utils)
- Validate input with Zod (body for POST/PATCH, query for GET, params always)
- Scope DB queries to session.user.organizationId (never trust client-sent org ID)
- Return consistent shape: { data, meta? } on success
- Use createError() for all errors: { statusCode, message, data?: { fieldErrors } }
- Log structured events: method, path, userId, tenantId, duration
index.get.ts: paginated list with filtering (status, priority, assignedTo)
index.post.ts: create task, run Drizzle insert, return created task
[id].patch.ts: partial update with optimistic concurrency (version field check)
[id].delete.ts: soft delete (set deletedAt), return 204
Show Drizzle ORM queries for each route.
5. Composables for Data Fetching
You are a Vue 3 composables expert.
Build a set of production composables for a Nuxt 4 app:
useApi<T>(endpoint, options):
- Wraps $fetch with: auth headers from session, base URL from runtime config
- Error normalisation: always return { data, error, loading } shape
- Retry: 3 times with exponential backoff on network errors only
- AbortController: cancel on component unmount or new call
usePaginatedTasks(projectId, filters):
- Calls useApi for paginated task list
- Cursor-based or offset pagination with has-more flag
- Auto-refetch when filters change (watchEffect)
- Merge: append new page results to existing list (infinite scroll support)
- Returns: { tasks, loading, error, hasMore, loadMore, refresh }
useOptimisticMutation<T>(mutationFn):
- Accepts: optimisticValue, onSuccess, onError callbacks
- Applies optimistic update to Pinia store immediately
- Calls mutationFn (API call)
- On success: confirm optimistic state
- On error: rollback optimistic state, show toast error
TypeScript strict. Show usage in 2 Vue components.
6. Vue Component Testing with Vitest
You are a Vue Testing Library + Vitest expert.
Write component tests for a TaskForm.vue component:
[PASTE COMPONENT CODE]
Requirements:
- renderWithProviders(): custom render wrapper with Pinia, Vue Router, i18n
- Test user behavior, not internals (no accessing component refs or internal state)
- Use userEvent for all interactions (typing, clicking, selecting)
- MSW (Mock Service Worker) for API calls
Test cases:
1. Renders all form fields with correct labels (accessibility query: getByLabelText)
2. Shows validation errors below each field on submit with empty form
3. Due date in past shows inline error without submit
4. Successful submit: calls API with correct payload, shows success toast, emits 'created' event
5. API error: shows error message, form remains submittable (not locked)
6. Loading state: submit button disabled and shows spinner during API call
7. Dirty form: navigate away → confirm dialog appears (useBeforeRouteLeave)
8. Keyboard: Tab through all fields in correct order, Enter submits form
vitest.config.ts setup with jsdom environment.
8. Nuxt Server Middleware for Auth
You are a Nuxt 4 full-stack engineer.
Implement server-side authentication middleware for a Nuxt 4 application:
Middleware: server/middleware/auth.ts (runs on every server request)
- Read JWT from Authorization header or __session cookie (cookie-first for SSR, header-first for API clients)
- Verify JWT using jose library (not jsonwebtoken — edge runtime compatible)
- On valid JWT: set event.context.user = { id, email, role, tenantId }
- On invalid/missing JWT for protected routes: throw createError({ statusCode: 401 })
- Public routes (no auth required): /api/auth/*, /api/public/*, all non-/api routes (handled by page-level auth)
Route protection in pages: definePageMeta({ middleware: 'auth' })
Nuxt route middleware: middleware/auth.ts (client-side guard that redirects to /login)
useAuth() composable:
- user: readonly computed from useState('user')
- isAuthenticated: computed boolean
- login(credentials) → POST /api/auth/login, set cookie, update state
- logout() → POST /api/auth/logout, clear cookie and state, redirect
Output: server middleware, route middleware, useAuth composable, and example protected page.
9. Nuxt Content with MDX for a Technical Blog
You are a Nuxt content engineer.
Set up Nuxt Content v3 for a technical blog with advanced features:
Content structure: content/blog/[slug].mdx — frontmatter: title, description, date, tags, author, draft
Features to implement:
1. Blog listing page: /blog — query all non-draft posts, sort by date, paginate 10/page with useAsyncData
2. Blog detail: /blog/[slug] — dynamic OG image generation with Satori, reading time calculation
3. MDX components: CodeBlock (syntax highlighting with Shiki, copy button, language badge), Callout (info/warning/danger variants), YouTubeEmbed
4. Search: full-text search across all blog posts using Nuxt Content's built-in search API
5. Related posts: query posts with matching tags, exclude current post, limit 3
6. RSS feed: /rss.xml server route that generates valid RSS 2.0 from all posts
7. Sitemap: auto-generate /sitemap.xml including all blog slugs
TypeScript: define CollectionSchema for blog posts with Zod validation of frontmatter
Output: nuxt.config.ts with content module setup, page components, MDX component examples, and the RSS route.
10. Vue 3 Animation with GSAP and Transitions
You are a Vue 3 animation engineer.
Implement smooth page transitions and component animations in a Nuxt 4 app:
Page transitions:
- Define pageTransition in nuxt.config.ts: name 'page', mode 'out-in'
- app.vue: <NuxtPage :transition="route.meta.pageTransition" />
- Fade transition: default (opacity 0 → 1, 200ms ease)
- Slide transition: dashboard pages (translateX -20px → 0, 300ms ease-out)
- Per-page override: definePageMeta({ pageTransition: { name: 'slide', mode: 'out-in' } })
GSAP animations with Vue 3 Composition API:
- useEntranceAnimation(el: Ref<HTMLElement | null>) composable: GSAP timeline that runs on onMounted, cleanup on onUnmounted
- Stagger animation for list items: gsap.from('.list-item', { opacity: 0, y: 20, stagger: 0.05 })
- ScrollTrigger for section reveals: fade-in when section enters viewport
<TransitionGroup> for dynamic lists:
- Task list reorder animation using FLIP technique (Vue's built-in move-class)
- Item add/remove with height animation (GSAP + Vue transition hooks: onEnter, onLeave)
Output: transition CSS classes, GSAP composable, and 3 example component implementations.
End-to-End Workflow: Full-Stack Nuxt Feature
Shipping a complete feature (team management with real-time presence) using chained Nuxt prompts:
- Server route (Prompt 4 variant): "Create GET /api/teams and POST /api/teams server routes in Nuxt 4. Validate POST body with Zod (name: string min 3, description: string optional). Use Drizzle ORM to query/insert. Scope to event.context.user.tenantId."
- Pinia store (Prompt 3 variant): "Create a useTeamsStore Pinia store: fetch teams from /api/teams with useAsyncData, optimistic create (push to local array before API response, rollback on failure), real-time sync via Nuxt's built-in WebSocket or useFetch polling."
- Component (Prompt 2 variant): "Create a TeamCard.vue component with script setup TypeScript. Props: team (typed from Drizzle schema). Display name, member avatars (max 5 with +N overflow), role badge, and a 'Manage' button. Emit 'select' with team ID."
- Page: "Create pages/teams/index.vue: use useTeamsStore, show skeleton while loading, empty state with create button, TeamCard grid with CSS Grid auto-fill."
- Tests (Prompt 6 variant): "Write Vitest component tests for TeamCard.vue: renders team name, shows correct member count overflow, emits 'select' on button click, renders empty avatar placeholder when team has no members."
Where AI Goes Wrong in Vue 3 + Nuxt
- Options API instead of Composition API. The most common failure. AI trained on pre-2022 Vue data defaults to the Options API with data(), methods, and computed properties. Always start Vue prompts with: "Use Vue 3 script setup with TypeScript."
- Vuex instead of Pinia. Specify Pinia explicitly — AI still reaches for Vuex for state management. They're structurally different enough that Vuex code won't migrate easily.
- Nuxt 3 vs Nuxt 4 differences. Nuxt 4 moved to a new composable layer and changed several APIs. AI trained before Nuxt 4's release generates Nuxt 3 patterns in Nuxt 4 projects. Specify "Nuxt 4" explicitly and verify the composable signatures against the docs.
- Missing h3 event handler syntax in server routes. Nuxt server routes use h3 under the hood. AI often generates incorrect event handler usage — wrong ways to read request body, wrong header access patterns. Always verify server route code against the h3 documentation.
- defineModel() not used for v-model in Vue 3.4+. AI still generates the pre-3.4 emit pattern (emit 'update:modelValue'). Since Vue 3.4, defineModel() is the correct pattern. Specify "Vue 3.4+ defineModel for v-model props."
7. Good vs Bad Vue/Nuxt Prompts
| Task | ❌ Bad Prompt | ✅ Good Prompt |
|---|---|---|
| Component | "Build a task form in Vue" | "Build TaskForm.vue with script setup, TypeScript, Vue 3 Composition API. Use VeeValidate + Zod schema. Fields: title (required, min 3), description (optional, textarea), dueDate (future dates only), assignee (async search combobox with 300ms debounce). Emit 'submit' with typed payload. Show field-level errors." |
| State | "Create a Pinia store" | "Create useTaskStore (Pinia Setup store) with TypeScript. State: Map<string,Task> for O(1) lookup. Actions: createTask with optimistic insert + rollback on API failure. Getter: overdueTasks computed from Map. Persist filter preferences only via pinia-plugin-persistedstate." |
| Server route | "Add an API to my Nuxt app" | "Write server/api/tasks/index.post.ts for Nuxt 4: requireUserSession() auth, Zod body validation, Drizzle insert scoped to session.user.organizationId, createError() on validation failure, return { data: createdTask } with 201 status." |
Before You Prompt: Vue 3 & Nuxt Context Setup
Vue 3's Composition API and Vue 2's Options API look completely different, and AI trained on Vue 2 tutorials produces code that compiles but misses all the ergonomic benefits of script setup. This block keeps everything in the modern Vue 3 paradigm:
Context for all Vue/Nuxt prompts in this session:
- Framework: Nuxt 4 (OR Vue 3 + Vite 6 SPA — specify which)
- Language: TypeScript, all components use <script setup lang="ts">
- State: Pinia 3 with setup stores (NOT Vuex, NOT Options stores)
- Nuxt: auto-imports enabled — do NOT manually import ref, computed, watch,
or any useXxx composable from 'vue' or '#imports'
- Styling: Tailwind CSS v4
Never generate:
- Options API (no data(), methods:, computed:, mounted:)
- Vuex (store module, mapState, mapGetters)
- Vue 2 lifecycle hooks (beforeDestroy → onBeforeUnmount, destroyed → onUnmounted)
- defineComponent() wrapper (script setup is always preferred)
The auto-imports line prevents a subtle but frustrating issue: Nuxt auto-imports all Vue composables and your own composables in composables/ — if AI adds explicit imports, they're either redundant or wrong path. The "Never generate" list for Vue 2 lifecycle hook names matters because both names coexist in training data and some models use them interchangeably.
3 Common Mistakes When Prompting AI for Vue & Nuxt
Mistake 1: Getting Options API instead of Composition API
Asking for "a Vue component" produces Options API output roughly 40% of the time — data(), methods: {}, computed: {}. This code works but doesn't coexist cleanly with Composition API components and misses the type inference benefits of script setup. Always say: "<script setup lang='ts'> only — no Options API, no defineComponent wrapper." If you're seeing Options API output even with this instruction, add a short example of a <script setup> component to anchor the format.
Mistake 2: Vuex patterns in Pinia stores
AI frequently generates Pinia stores using the Options Store syntax (state: () => ({}), getters: {}, actions: {}) which looks like Vuex. The modern equivalent is the Setup Store: a function using ref(), computed(), and regular functions — exactly like script setup. Specify: "Pinia 3 Setup Store syntax — a function with ref/computed/return, not Options Store with state/getters/actions." The Setup Store has better TypeScript inference and feels more natural in a Composition API codebase.
Mistake 3: Missing Nuxt's rendering mode context
Nuxt 4 supports universal rendering (SSR + client hydration), SPA mode, and static generation. AI generates components without considering which rendering mode they run in — resulting in window/document access errors on the server, or fetch calls that run twice (once on server, once on client). For every component prompt, specify: "this runs in universal (SSR) mode — use useAsyncData or useFetch for data fetching, never fetch() directly in setup."
Further Reading
Resources for AI-assisted Vue and Nuxt development:
- How engineering teams use AI to ship frontend faster — AI strategies for Vue/Nuxt projects: component generation, composable design, and automated testing
- How to write the perfect AI prompt — the prompting principles behind every template in this guide
- AI Coding Prompt Library — 50+ copy-ready prompts for Vue, Nuxt, Pinia, Vitest, and frontend performance
Generate a custom Vue/Nuxt prompt → Try PromptPrepare free
Help & Answers
Frequently Asked Questions
Found this helpful?
Save it to your library or share with your team.
Keep Reading