Nuxt Pages and Routing — File-Based Routing in Nuxt 3
In this tutorial, you will learn about Nuxt Pages and Routing. We cover key concepts, practical examples, and best practices to help you master this topic.
Learn Nuxt 3 file-based routing, dynamic routes, route parameters, and navigation components for building multi-page Vue applications.
In this lesson, you'll understand how Nuxt 3 maps files to routes, handles dynamic segments, and provides page metadata.
What You'll Learn
How file-based routing works in Nuxt 3, how to create dynamic routes with parameters, and how to use <NuxtLink> for navigation.
Why It Matters
Nuxt's file-based routing eliminates route configuration. The file structure IS the route structure, making navigation intuitive and scalable.
flowchart LR
A[pages/] --> B[index.vue /]
A --> C[about.vue /about]
A --> D[blog/]
D --> E[blog/index.vue /blog]
D --> F[blog/[slug].vue /blog/:slug]
style A fill:#00dc82,color:#fff
Basic Pages
pages/
├── index.vue → /
├── about.vue → /about
├── contact.vue → /contact
├── blog/
│ ├── index.vue → /blog
│ └── [slug].vue → /blog/:slug
└── categories/
└── [category]/
└── [id].vue → /categories/:category/:id
<!-- pages/about.vue -->
<template>
<div>
<h1>About Us</h1>
<p>This page is at /about.</p>
</div>
</template>
Output: The file path determines the URL. /about renders the About page.
Dynamic Routes
Use square brackets for dynamic segments:
<!-- pages/blog/[slug].vue -->
<script setup>
const route = useRoute();
const { data: post } = await useFetch(`/api/posts/${route.params.slug}`);
</script>
<template>
<article>
<h1>{{ post.title }}</h1>
<div v-html="post.content" />
</article>
</template>
Output: Navigating to /blog/hello-world sets route.params.slug to "hello-world" and fetches the matching post.
Catch-All Routes
Use [...slug].vue for catch-all routes:
<!-- pages/[...slug].vue -->
<script setup>
const route = useRoute();
// route.params.slug is an array of path segments
</script>
<template>
<div>
<p>You are at: /{{ route.params.slug?.join('/') }}</p>
</div>
</template>
Output: /a/b/c results in route.params.slug = ['a', 'b', 'c'].
Navigation with NuxtLink
<template>
<nav>
<NuxtLink to="/">Home</NuxtLink>
<NuxtLink to="/about">About</NuxtLink>
<NuxtLink to="/blog">Blog</NuxtLink>
<NuxtLink :to="`/blog/${post.slug}`">{{ post.title }}</NuxtLink>
</nav>
</template>
Output: <NuxtLink> renders an <a> tag with client-side navigation. It prefetches linked pages when visible.
Page Metadata
Set page-specific metadata with definePageMeta:
<script setup>
definePageMeta({
title: 'About Us',
description: 'Learn more about our team and mission',
layout: 'default',
middleware: 'auth'
});
</script>
Output: The page has SEO metadata, uses the default layout, and runs the auth middleware before rendering.
Common Mistakes
- Forgetting square brackets for dynamic routes:
[slug].vuenot:slug.vue. Nuxt uses bracket syntax like Vue Router 4. - Not using
useRoutefor params:route.params.slugreturns the dynamic segment. Access it viauseRoute(). - Overlapping routes:
[slug].vueandabout.vueboth match/about. More specific files take priority. - Using
<a>instead of<NuxtLink>: Regular<a>tags cause full page reloads. Always use<NuxtLink>. - Missing
definePageMetafor SEO: Without it, pages lack title and meta tags. Set them for every page.
Practice Questions
What URL does
pages/blog/[slug].vuematch? Answer:/blog/:slugwhere:slugis any value like/blog/hello-world.How do you access route parameters in a page component? Answer: Use
const route = useRoute()thenroute.params.slug.What component replaces
<a>for internal navigation? Answer:<NuxtLink>. It provides client-side navigation with prefetching.How do you set page metadata in Nuxt 3? Answer: Use
definePageMeta({ title: '...', description: '...' })inside<script setup>.
Challenge
Create a blog with: list page at /blog, individual posts at /blog/[slug], categories at /categories/[category], and a catch-all page at [...slug].vue for custom paths.
Mini Project
Build a documentation site with Nuxt 3 routing: top-level pages (Getting Started, API, Examples), dynamic docs at /docs/[section]/[page], and versioned docs at /docs/v1/[...slug].
FAQ
What's Next
Learn about Nuxt Layouts to create reusable page layouts with headers, footers, and sidebars.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro