Skip to content
Watch the complete Next.js 15 course on YouTube

Dynamic routes

This page explains how to create dynamic routes in Next.js.

Understanding dynamic routes

While nested routes work well for predefined paths, they become impractical when dealing with data-driven routes. Consider an e-commerce site with product pages — creating individual folders for each product would be inefficient and hard to maintain.

  • Directoryapp/
    • Directoryproducts/
      • Directoryiphone/
        • page.tsx /products/iphone
      • Directorymacbook/
        • page.tsx /products/macbook
      • Directoryipad/
        • page.tsx /products/ipad
      • Directoryairpods/
        • page.tsx /products/airpods (and the list goes on…)

Dynamic routes allow you to create pages that can match multiple URLs using a single page component. They’re essential when building pages where the path segments are not known ahead of time.

Creating dynamic routes

To create a dynamic route in Next.js:

  1. Create a folder with square brackets containing the parameter name (e.g., [productId])
  2. Add a page.tsx file inside this folder
  3. Next.js will map any matching URL pattern to this page component
  • Directoryapp/
    • Directoryproducts/
      • Directory[productId]/
        • page.tsx /products/123 or /products/iphone

Here’s a basic dynamic product details page:

app/products/[productId]/page.tsx
export default function ProductDetails() {
return <h1>Product details page</h1>;
}

How dynamic routes work

When you create a folder with square brackets (e.g., [productId]), Next.js treats it as a dynamic segment. This means:

  • /products/1 maps to the same page component as /products/2
  • The parameter can be any string, not just numbers (e.g., /products/iphone)
  • A single component handles all matching routes

Accessing route parameters

To access the dynamic segments of the URL, Next.js provides a params prop to your page component. For server components, this is available as a promise that you can await.

app/products/[productId]/page.tsx
export default async function ProductDetails({
params,
}: {
params: Promise<{ productId: string }>;
}) {
const { productId } = await params;
return <h1>Details about product {productId}</h1>;
}

The params object contains key-value pairs where:

  • The key is the name you specified in brackets (e.g., productId)
  • The value is the actual URL segment

For example:

  • URL /products/iphoneparams.productId = "iphone"
  • URL /products/123params.productId = "123"

Dynamic routes are particularly useful for:

  • Product pages in e-commerce sites
  • Blog post pages
  • User profiles
  • Any content that follows a consistent URL pattern but has variable values