404 Not Found

404 Not Found


nginx

Pages and Routes

While adding product detail pages to MegaShop, Bob manually configured 50 vue-router routes. Every time a new product was listed, he had to edit the route files—it was a real pain. Charlie told him that Nuxt 3 automatically generates routes based on file conventions, so creating a file is the same as creating a route.

1. What You'll Learn


2. A True Story of an Administrator

(1) Pain Point: The Nightmare of Manual Routing Configuration

Bob set up 1,000 routes for MegaShop using the traditional Vue Router—one for each category and each product page. Every time a new product was listed, he had to edit the route file; if he missed even one, it resulted in a 404 error. Alice couldn't find the products, and the complaint rate skyrocketed.

(2) Solutions for Nuxt File Routing

With Nuxt 3's file-based routing, Bob just needs to create a file:

TEXT
pages/products/[id].vue  →  /products/:id

One million products in a single file, with dynamic parameters automatically passed through.

(3) Benefits: Zero-Configuration Routing

Bob no longer has to write route configurations—adding a new page is as simple as creating a new file, and 1 million product detail pages require just one [id].vue.


3. File Routing Rules

(1) Directory-to-Route Mapping Process

100%
flowchart LR
    A[pages/index.vue] -->|"/"| B[Root Route]
    C[pages/about.vue] -->|"/about"| C2[About Route]
    D[pages/products/index.vue] -->|"/products"| D2[Product List Route]
    E[pages/products/[id].vue] -->|"/products/:id"| E2[Product Detail Route]
    F[pages/categories/[...slug].vue] -->|"/categories/:slug*"| F2[Catch-all Route]

(2) File Routing Mapping Rules

File Path Generated Route Description
pages/index.vue / Home
pages/about.vue /about Static page
pages/products/index.vue /products Product List
pages/products/[id].vue /products/:id Dynamic Parameter
pages/categories/[slug].vue /categories/:slug Dynamic Parameters
pages/categories/[...slug].vue /categories/:slug(*) Wildcard route
pages/404.vue /404 Custom 404

(1) ▶ Example: Basic Page Routing

VUE
<!-- pages/index.vue -->
<template>
  <div>
    <h1>MegaShop - Millions of Products</h1>
    <NuxtLink to="/products">Browse Products</NuxtLink>
  </div>
</template>

Output:

TEXT
// Execution Successful
VUE
<!-- pages/about.vue -->
<template>
  <div>
    <h1>About MegaShop</h1>
    <p>Serving over 1 million products worldwide</p>
  </div>
</template>

4. Dynamic Routing

(1) Single-Parameter Dynamic Routing

Use the [param] syntax to define dynamic routing parameters.

(1) ▶ Example: Dynamic Routing for Product Detail Pages

VUE
<!-- pages/products/[id].vue -->
<template>
  <div>
    <h1>Product #{{ route.params.id }}</h1>
    <p>Price: ${{ product?.price }} USD</p>
  </div>
</template>

<script setup lang="ts">
const route = useRoute()
const { data: product } = await useFetch(`/api/products/${route.params.id}`)
</script>

Output:

TEXT
// Execution Successful

(2) Wildcard Routes

Use the [...slug] syntax to capture multi-level paths.

(2) ▶ Example: Multi-level Categorized Wildcard Routing

VUE
<!-- pages/categories/[...slug].vue -->
<template>
  <div>
    <h1>Category: {{ slugPath }}</h1>
    <p>{{ products.length }} products found</p>
  </div>
</template>

<script setup lang="ts">
const route = useRoute()
// /categories/electronics/headphones → slug = ['electronics', 'headphones']
const slugPath = computed(() => (route.params.slug as string[]).join('/'))
const { data: products } = await useFetch(`/api/categories/${slugPath.value}`)
</script>

Output:

TEXT
// Execution Successful

(3) Dynamic Routing Parameter Types

Syntax Match Example URL params value
[id] Single section /products/123 { id: '123' }
[id].vue + index.vue Optional /products or /products/123 { id?: '123' }
[...slug] Multi-segment wildcard /a/b/c { slug: ['a','b','c'] }

5. Nested Routes

(1) Nested Routing Structure

Nested routing requires a parent page (a .vue file with the same name) and a child directory to work together:

TEXT
pages/
├── products/
│   ├── index.vue          # /products (child)
│   ├── [id].vue           # /products/:id (child)
│   └── edit.vue           # /products/edit (child)
└── products.vue           # /products (parent with <NuxtPage />)

(1) ▶ Example: Nested Routes on a Product Page

VUE
<!-- pages/products.vue - Parent layout -->
<template>
  <div>
    <nav class="product-nav">
      <NuxtLink to="/products">All Products</NuxtLink>
      <NuxtLink to="/products/featured">Featured</NuxtLink>
    </nav>
    <!-- Child routes render here -->
    <NuxtPage />
  </div>
</template>

Output:

TEXT
// Execution Successful
VUE
<!-- pages/products/index.vue - Child: product list -->
<template>
  <div>
    <h1>All Products</h1>
    <p>1 million products available</p>
  </div>
</template>
VUE
<!-- pages/products/[id].vue - Child: product detail -->
<template>
  <div>
    <h1>Product Detail</h1>
    <p>ID: {{ route.params.id }}</p>
  </div>
</template>

(2) Comparison of Nested Routes vs. Layout

Dimension Nested Routing Layout
Mechanism Parent page + NuxtPage slot layouts/ + NuxtLayout
Routing Relationships Parent-Child Routes Sharing Layouts Page-Level Layout Switching
Data Retrieval Parent and child each use useFetch Layout does not retrieve data
Use Cases Category → Product → Review Hierarchy Overall Page Layout (Header/Footer)

6. Programmatic Navigation

(1) Comparison of Three Navigation Methods

API Purpose Available on the server Use Case
navigateTo() Programmatic navigation Redirect after login
useRouter().push() Client-side navigation Navigation via button click
NuxtLink Declarative Links Navigation in Templates

(1) ▶ Example: navigateTo Server-Side Redirect

TYPESCRIPT
// In middleware or server-side context
export default defineNuxtRouteMiddleware((to) => {
  const isAuthenticated = useState('isAuthenticated')

  if (!isAuthenticated.value && to.path.startsWith('/admin')) {
    return navigateTo('/login', { redirectCode: 302 })
  }
})

Output:

TEXT
// Execution Successful

(2) ▶ Example: useRouter client-side navigation

VUE
<template>
  <button @click="goToProduct(product.id)">
    View Details
  </button>
</template>

<script setup lang="ts">
const router = useRouter()

function goToProduct(id: number) {
  router.push(`/products/${id}`)
}
</script>

Output:

TEXT
// Execution Successful

(3) ▶ Example: Retrieving parameters with useRoute

VUE
<script setup lang="ts">
const route = useRoute()

// Access params
const productId = route.params.id         // From [id].vue
const categorySlug = route.params.slug     // From [...slug].vue

// Access query params
// /products?category=electronics&sort=price
const category = route.query.category      // 'electronics'
const sort = route.query.sort              // 'price'
</script>

Output:

TEXT
// Execution Successful

7. Hands-On Guide to Multi-Level Routing in MegaShop

(1) MegaShop Routing Plan

URL File Function
/ pages/index.vue Home
/products pages/products/index.vue Product List
/products/[id] pages/products/[id].vue Product Details
/categories/[category] pages/categories/[category].vue Category Page
/categories/[category]/[subcategory] pages/categories/[...slug].vue Subcategory
/cart pages/cart.vue Shopping Cart
/checkout pages/checkout.vue Checkout Page
/admin pages/admin/index.vue Admin Dashboard
/admin/products pages/admin/products/index.vue Product Management
/404 pages/404.vue 404 Page

(1) ▶ Example: MegaShop 404 Page

VUE
<!-- pages/404.vue -->
<template>
  <div class="not-found">
    <h1>404 - Product Not Found</h1>
    <p>The product you're looking for doesn't exist.</p>
    <NuxtLink to="/products">Browse all products</NuxtLink>
  </div>
</template>

Output:

TEXT
// Execution Successful

8. Comprehensive Example: The MegaShop Routing System

VUE
<!-- pages/index.vue - Homepage -->
<template>
  <div>
    <section class="hero">
      <h1>MegaShop</h1>
      <p>Over 1 million products, delivered worldwide</p>
      <NuxtLink to="/products">Shop Now</NuxtLink>
    </section>
    <section class="featured">
      <ProductCard v-for="p in featured" :key="p.id" :product="p" />
    </section>
  </div>
</template>

<script setup lang="ts">
const { data: featured } = await useFetch('/api/products/featured')
</script>
VUE
<!-- pages/products/[id].vue - Product Detail -->
<template>
  <div v-if="product">
    <h1>{{ product.name }}</h1>
    <p class="price">${{ product.price }} USD</p>
    <button @click="addToCart">Add to Cart</button>
    <button @click="goBack">Back to List</button>
  </div>
  <div v-else>
    <p>Product not found</p>
    <NuxtLink to="/products">Browse Products</NuxtLink>
  </div>
</template>

<script setup lang="ts">
const route = useRoute()
const router = useRouter()
const { data: product } = await useFetch(`/api/products/${route.params.id}`)

function addToCart() {
  navigateTo('/cart')
}

function goBack() {
  router.back()
}
</script>

❓ FAQ

Q Are the parameters for dynamic routing strings or numbers?
A URL parameters are always strings. If you need numbers, convert them manually: Number(route.params.id), or let the API's return type determine the value when using useFetch.
Q What is the difference between [id].vue and [...slug].vue?
A [id] matches only a single path segment (/products/123), while [...slug] matches a multi-segment path (/a/b/c), where slug is an array. Catch-all routes are suitable for categories with an unlimited number of levels.
Q Does the parent page for a nested route have to exist?
A Yes, a nested route is formed only when both the parent page products.vue and the subdirectory products/ exist. If you only want the child route, do not create the parent page.
Q What is the difference between NuxtLink and a regular a tag?
A NuxtLink is used for client-side navigation (without refreshing the page), while the a tag triggers a full page refresh. Use NuxtLink for internal navigation and the a tag for external links.
Q How do I set up a custom 404 page?
A Simply create a pages/404.vue file. Nuxt 3 automatically displays this page when no route matches the request. You can also handle it in a catch-all route.
Q What is the relationship between routeRules and routes?
A routeRules are configured in nuxt.config.ts to specify rendering strategies (SSR/ISR/CSR) based on route paths; they do not affect route definitions. Routes are defined by the files in the pages/ directory; routeRules only control rendering behavior.

📖 Summary


📝 Exercises

  1. Basic Exercise (Difficulty: ⭐): Create pages/about.vue and pages/contact.vue, and verify that the routes are generated automatically.
  2. Advanced Problem (Difficulty ⭐⭐): Implement /products/[category]/[id] two-level dynamic routing and display the "category" and "id" parameters on the page.
  3. Challenge (Difficulty: ⭐⭐⭐): Implement a catch-all route [...slug].vue that can render multi-level paths such as /docs/getting-started/installation and display a breadcrumb navigation bar.

---|

Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏