Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Nuxt 4+ development patterns: server routes, file-based routing, middleware, composables, and h3 v1 / nitropack v2.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/routing.md
1# Nuxt File-Based Routing23## When to Use45Working with `pages/` or `layouts/` directories, file-based routing, navigation.67## File-Based Routing Basics89`pages/` folder structure directly maps to routes. File names determine URLs.1011## Naming Conventions1213**Key principles:**1415- **ALWAYS use descriptive params:** `[userId].vue` NOT `[id].vue`16- **Optional params:** `[[paramName]].vue`17- **Catch-all:** `[...path].vue`18- **Route groups for organization:** `(folder)/` groups files without affecting URLs1920## Red Flags - Stop and Check Skill2122If you're thinking any of these, STOP and re-read this skill:2324- "String paths are simpler than typed routes"25- "Generic param names like [id] are fine"26- "I remember how Nuxt 3 worked"2728All of these mean: You're about to use outdated patterns. Use Nuxt 4 patterns instead.2930## File Structure Example3132```33pages/34├── index.vue # /35├── about.vue # /about36├── [...slug].vue # catch-all for 40437├── users.vue # parent route (layout for /users/*)38└── users/39├── index.vue # /users40└── [userId].vue # /users/:userId41```4243## Route Groups for Organization4445Route groups organize files WITHOUT affecting URLs. Wrap folder names in parentheses:4647```48pages/49├── (marketing)/ # group folder (ignored in URL)50│ ├── about.vue # /about (not /marketing/about)51│ └── pricing.vue # /pricing52└── (admin)/ # group folder (ignored in URL)53├── dashboard.vue # /dashboard54└── settings.vue # /settings55```5657**Use route groups to:**5859- Organize pages by feature/team60- Group related routes without affecting URLs61- Keep large projects maintainable62- Apply middleware to specific groups (via `route.meta.groups`)6364**Access route groups in middleware:**6566```ts67// middleware/auth.global.ts68export default defineNuxtRouteMiddleware((to) => {69// Check if route is in admin group70if (to.meta.groups?.includes('admin')) {71const auth = useAuthStore()72if (!auth.isAdmin) return navigateTo('/')73}74})75```7677## Parent Routes (Layouts)7879Parent route = layout for nested routes:8081```vue82<!-- pages/users.vue -->83<template>84<div class="users-layout">85<nav>86<NuxtLink to="/users">All Users</NuxtLink>87<NuxtLink to="/users/create">Create User</NuxtLink>88</nav>89<NuxtPage />90</div>91</template>92```9394Child routes:9596```97pages/98├── users.vue # Parent route with <NuxtPage />99└── users/100├── index.vue # /users101├── [userId].vue # /users/:userId102└── create.vue # /users/create103```104105## definePage() for Route Customization106107```vue108<script setup lang="ts">109definePage({110name: 'user-profile',111path: '/profile/:userId', // Override default path112alias: ['/me', '/profile'],113meta: {114requiresAuth: true,115title: 'User Profile',116roles: ['user', 'admin']117}118})119</script>120121<template>122<div>Profile content</div>123</template>124```125126## Typed Router127128**ALWAYS use typed routes for navigation:**129130```ts131// ✅ Type-safe with route name132await navigateTo({ name: '/users/[userId]', params: { userId: '123' } })133134// ❌ String-based (not type-safe, avoid)135await navigateTo('/users/123')136```137138**REQUIRED: Check `typed-router.d.ts` for available route names and params before navigating.**139140## useRoute with Types141142Pass route name for stricter typing:143144```ts145// Generic route146const route = useRoute()147148// Typed route (preferred)149const route = useRoute('/users/[userId]')150// route.params.userId is now typed correctly151```152153## Navigation154155```ts156// Navigate to route157await navigateTo('/about')158await navigateTo({ name: '/users/[userId]', params: { userId: '123' } })159160// Navigate with query161await navigateTo({ path: '/search', query: { q: 'nuxt' } })162163// External redirect164await navigateTo('https://nuxt.com', { external: true })165166// Replace history167await navigateTo('/login', { replace: true })168169// Open in new tab170await navigateTo('/docs', { open: { target: '_blank' } })171```172173## Route Meta & Middleware174175```vue176<script setup lang="ts">177definePageMeta({178middleware: ['auth', 'admin'],179layout: 'dashboard',180meta: {181requiresAuth: true182}183})184</script>185```186187## Dynamic Layout Switching188189Use `setPageLayout()` to switch layouts programmatically:190191```vue192<script setup lang="ts">193const user = useUser()194195// Switch layout based on auth state196if (!user.value) {197setPageLayout('guest')198} else {199setPageLayout('dashboard')200}201202// With layout props (Nuxt 4.3+)203setPageLayout('dashboard', {204sidebar: 'collapsed',205theme: 'dark'206})207</script>208```209210## Dynamic Routes Patterns211212```213[userId].vue # /users/123214[[slug]].vue # /blog or /blog/post (optional)215[...path].vue # /a/b/c (catch-all)216[[...path]].vue # / or /a/b/c (optional catch-all)217```218219## Best Practices220221- **`index.vue` for index routes** - valid and correct for creating default routes222- **Route groups `(folder)/` for organization** - group files without affecting URLs223- **Descriptive param names** - `[userId]` not `[id]`, `[postSlug]` not `[slug]`224- **Type-safe navigation** - use route names, not strings225- **Check typed-router.d.ts** for available routes226- **Parent routes for layouts** - `users.vue` with `<NuxtPage />`227- **Use definePage** for custom paths/aliases228- **Catch-all for 404** - `[...path].vue` or `[...slug].vue`229230## Common Mistakes231232| ❌ Wrong | ✅ Right |233| ---------------------------- | ----------------------------------------------------------------- |234| `[id].vue` | `[userId].vue` or `[postId].vue` |235| `navigateTo('/users/' + id)` | `navigateTo({ name: '/users/[userId]', params: { userId: id } })` |236| `<Nuxt />` | `<NuxtPage />` |237| Separate layouts/ folder | Parent routes with `<NuxtPage />` |238239## Resources240241- Nuxt routing: https://nuxt.com/docs/guide/directory-structure/pages242- File-based routing: https://nuxt.com/docs/getting-started/routing243