Routing
Nuxt uses file-system routing based on vue-router. Files in app/pages/ automatically create routes.
Basic Routing
pages/
โโโ index.vue โ /
โโโ about.vue โ /about
โโโ posts/
โโโ index.vue โ /posts
โโโ [id].vue โ /posts/:idDynamic Routes
Use brackets for dynamic segments:
pages/
โโโ users/
โ โโโ [id].vue โ /users/:id
โโโ posts/
โ โโโ [...slug].vue โ /posts/* (catch-all)
โโโ [[optional]].vue โ /:optional? (optional param)Access route parameters:
<script setup lang="ts">
const route = useRoute()
// /posts/123 โ route.params.id = '123'
console.log(route.params.id)
</script>Navigation
NuxtLink Component
<template>
<nav>
<NuxtLink to="/">Home</NuxtLink>
<NuxtLink to="/about">About</NuxtLink>
<NuxtLink :to="{ name: 'posts-id', params: { id: 1 } }">Post 1</NuxtLink>
</nav>
</template>NuxtLink automatically prefetches linked pages when they enter the viewport.
Programmatic Navigation
<script setup lang="ts">
const router = useRouter()
function goToPost(id: number) {
navigateTo(`/posts/${id}`)
// or
router.push({ name: 'posts-id', params: { id } })
}
</script>Route Middleware
Named Middleware
// middleware/auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
const isAuthenticated = false // Your auth logic
if (!isAuthenticated) {
return navigateTo('/login')
}
})Apply to pages:
<script setup lang="ts">
definePageMeta({
middleware: 'auth',
// or multiple: middleware: ['auth', 'admin']
})
</script>Global Middleware
Name files with .global suffix:
// middleware/logging.global.ts
export default defineNuxtRouteMiddleware((to, from) => {
console.log('Navigating to:', to.path)
})Inline Middleware
<script setup lang="ts">
definePageMeta({
middleware: [
function (to, from) {
// Inline middleware logic
},
],
})
</script>Page Meta
Configure page-level options:
<script setup lang="ts">
definePageMeta({
title: 'My Page',
layout: 'custom',
middleware: 'auth',
validate: (route) => {
// Return false for 404, or object with status/statusText
return /^\d+$/.test(route.params.id as string)
},
})
</script>Route Validation
<script setup lang="ts">
definePageMeta({
validate: (route) => {
// Must return boolean or object with status
return typeof route.params.id === 'string' && /^\d+$/.test(route.params.id)
},
})
</script>Layouts
Define layouts in app/layouts/:
<!-- layouts/default.vue -->
<template>
<div>
<header>Header</header>
<slot />
<footer>Footer</footer>
</div>
</template><!-- layouts/admin.vue -->
<template>
<div class="admin">
<AdminSidebar />
<main>
<slot />
</main>
</div>
</template>Use in pages:
<script setup lang="ts">
definePageMeta({
layout: 'admin',
})
</script>Dynamic layout:
<script setup lang="ts">
const layout = ref('default')
function enableAdmin() {
setPageLayout('admin')
}
</script>Passing Props to Layouts (Nuxt 4.4+)
Use the object syntax for layout to pass typed props to the layout component:
<!-- app/pages/dashboard.vue -->
<script setup lang="ts">
definePageMeta({
layout: { name: 'panel', props: { sidebar: true, title: 'Dashboard' } },
})
</script><!-- app/layouts/panel.vue -->
<script setup lang="ts">
const props = defineProps<{ sidebar?: boolean, title?: string }>()
</script>Props are fully typed from the layout's defineProps. Also works dynamically: setPageLayout('panel', { sidebar: true }).
Named Views
A route can render into multiple <NuxtPage> outlets. Add named view files with the name@view.vue convention next to the default route file:
pages/
โโโ parent.vue
โโโ parent/
โโโ child.vue โ default <NuxtPage />
โโโ child@sidebar.vue โ <NuxtPage name="sidebar" /><!-- pages/parent.vue -->
<template>
<NuxtPage />
<aside><NuxtPage name="sidebar" /></aside>
</template>definePageMeta is read from the default route file only.
Navigation Hooks
<script setup lang="ts">
onBeforeRouteLeave((to, from) => {
// Confirm before leaving
const answer = window.confirm('Leave?')
if (!answer) return false
})
onBeforeRouteUpdate((to, from) => {
// Called when route changes but component is reused
})
</script><!--
Source references:
- https://nuxt.com/docs/4.x/getting-started/routing
- https://nuxt.com/docs/4.x/directory-structure/app/pages
- https://nuxt.com/docs/4.x/directory-structure/app/middleware
- https://nuxt.com/docs/4.x/api/utils/define-page-meta
-->