Skip to content

Nuxt Pages and Routing — File-Based Routing in Nuxt 3

DodaTech Updated 2026-06-28 3 min read

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'].

<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

  1. Forgetting square brackets for dynamic routes: [slug].vue not :slug.vue. Nuxt uses bracket syntax like Vue Router 4.
  2. Not using useRoute for params: route.params.slug returns the dynamic segment. Access it via useRoute().
  3. Overlapping routes: [slug].vue and about.vue both match /about. More specific files take priority.
  4. Using <a> instead of <NuxtLink>: Regular <a> tags cause full page reloads. Always use <NuxtLink>.
  5. Missing definePageMeta for SEO: Without it, pages lack title and meta tags. Set them for every page.

Practice Questions

  1. What URL does pages/blog/[slug].vue match? Answer: /blog/:slug where :slug is any value like /blog/hello-world.

  2. How do you access route parameters in a page component? Answer: Use const route = useRoute() then route.params.slug.

  3. What component replaces <a> for internal navigation? Answer: <NuxtLink>. It provides client-side navigation with prefetching.

  4. 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

Does Nuxt 3 support nested routes?

: Yes. Directory nesting creates nested routes. Use <NuxtPage> in layouts to render child routes.

Can I use Vue Router directly?

: Nuxt uses Vue Router under the hood. You can access the router via useRouter() for programmatic navigation.

How do I create a 404 page?

: Create pages/[...slug].vue for custom 404 handling. Check if the route exists and show a 404 message.

Does Nuxt 3 support route transitions?

: Yes. Use Vue's <Transition> component or Nuxt's pageTransition in definePageMeta or nuxt.config.ts.

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