Vue Nuxt Agent Rules
Project Context
- Use Nuxt 3 with Vue 3 Composition API and TypeScript strict mode.
- Use `<script setup lang="ts">` in all components — never Options API.
- Leverage Nuxt's auto-import for Vue composables, Nuxt utilities, and components.
- Use Pinia for global state and `useFetch`/`useAsyncData` for server state.
Code Style & Structure
- Place components in `app/components/` for auto-import — use `Folder/ComponentName.vue` for namespaced imports.
- Place composables in `app/composables/` — auto-imported and prefixed with `use`.
- Place server utilities in `server/utils/` — auto-imported within `server/` only.
- Place Pinia stores in `app/stores/` — manually import them in components.
- Place pages in `app/pages/` for file-based routing. Use `[param].vue` for dynamic segments.
- Use `app/layouts/` for reusable page layouts configured via `definePageMeta`.
Component Patterns
- Use `defineProps<Props>()` for typed props and `defineEmits<Emits>()` for typed events.
- Use `defineModel()` (Vue 3.4+) for two-way binding in form inputs and controlled components.
- Use `defineExpose({ method })` only when a parent needs direct imperative access to the child.
- Keep templates clean — extract complex conditional logic into computed properties or composables.
- Use `<Teleport to="body">` for modals and tooltips to avoid z-index and overflow clipping issues.
- Prefer slots over prop-driven content variation to keep parent components flexible.
Data Fetching
- Use `useFetch('/api/resource')` for component-level SSR-compatible data fetching.
- Use `useAsyncData('key', () => $fetch('/api/resource'))` when you need explicit cache key control.
- Use `$fetch` in event handlers and actions — it is not SSR-aware and does not deduplicate on server.
- Use `lazy: true` on `useFetch` for non-critical data that should not block navigation.
- Use `server: false` on `useFetch` for client-only data (user preferences, real-time data).
- Refresh data with `refresh()` returned from `useFetch` after mutations.
Server Routes
- Define API routes in `server/api/` with method-based naming: `users.get.ts`, `users.post.ts`.
- Export a default `defineEventHandler(async (event) => { ... })` from each server route file.
- Validate request bodies with `readValidatedBody(event, schema.parse)` using Zod schemas.
- Return proper status codes with `setResponseStatus(event, 201)` for created resources.
- Use `getRequestHeader`, `getCookie`, and `getQuery` helpers from `h3` for request data access.
- Place shared server utilities in `server/utils/` for auto-import within server routes.
State Management
- Use `useState<T>('key', () => initialValue)` for SSR-safe shared state within Nuxt.
- Use Pinia with the Setup Store pattern for complex global state: `defineStore('id', () => { ... })`.
- Use `storeToRefs(store)` to destructure store state reactively in components.
- Keep store actions responsible for all state mutations — never mutate store state directly in components.
- Use `$patch` on options-style Pinia stores for batch state updates.
Routing & Navigation
- Use `definePageMeta({ layout: 'auth', middleware: 'auth' })` for per-page layout and middleware config.
- Create route middleware in `app/middleware/` — export a default function receiving `to` and `from`.
- Use `navigateTo('/path')` in middleware to redirect programmatically.
- Use `<NuxtLink>` for all internal navigation — it prefetches linked pages automatically.
- Use `useRoute()` for reading params and query strings. Use `useRouter()` for programmatic navigation.
SEO & Meta
- Use `useSeoMeta({ title, description, ogImage })` for clean, typed meta tag management.
- Use `useHead({ link: [{ rel: 'canonical', href: url }] })` for additional head elements.
- Define default meta in `nuxt.config.ts` with `app.head` for site-wide fallbacks.
- Use `<NuxtImg>` from `@nuxt/image` for optimized images with automatic WebP conversion.
Error Handling
- Create `app/error.vue` for the global error page — handle `statusCode` and `message` from `useError()`.
- Use `createError({ statusCode: 404, message: 'Not found' })` from `h3` in server routes.
- Use `showError(error)` in client-side composables to display the error page programmatically.
- Clear errors with `clearError({ redirect: '/' })` after user-initiated recovery.
Performance
- Use `<LazyComponentName>` prefix for lazy-loaded components to defer their JavaScript.
- Enable Nuxt's built-in image optimization with `@nuxt/image` and the `<NuxtPicture>` component.
- Configure `routeRules` in `nuxt.config.ts` to set caching strategy per route: `swr`, `isr`, `static`.
- Use `<NuxtPage keepalive />` to preserve component state during navigation between tabs.
Testing
- Use `@nuxt/test-utils` with Vitest for Nuxt-specific component and composable testing.
- Use `mountSuspended` from `@nuxt/test-utils/runtime` to test async components with SSR context.
- Test server routes with `$fetch` inside Nuxt test utils with a running test server.
- Mock Pinia stores with `createTestingPinia` for isolated component tests.