Next.js Dynamic Routes

Dynamic routes let you create one page template that works for many different URLs. Instead of making a separate page for each blog post, you create one dynamic page that handles all of them. The URL changes, but the same file handles every request.

The Problem Dynamic Routes Solve

Imagine a blog with 500 posts. Without dynamic routes, you would need 500 separate page files. That is not practical. Dynamic routes let you create one file and use the URL itself to decide what content to show.

WITHOUT DYNAMIC ROUTES (impractical):
app/blog/post-1/page.js
app/blog/post-2/page.js
app/blog/post-3/page.js
... 500 more files

WITH DYNAMIC ROUTES (practical):
app/blog/[slug]/page.js   ← One file handles all posts

Creating a Dynamic Route

Wrap the folder name in square brackets to make it dynamic. The name inside the brackets becomes a variable called a parameter.

app/blog/[slug]/page.js

This single file now responds to:

yoursite.com/blog/hello-world
yoursite.com/blog/my-first-post
yoursite.com/blog/nextjs-tutorial

Reading the Dynamic Parameter

Inside your page file, Next.js passes the dynamic value through a params object. You access it like this:

export default function BlogPost({ params }) {
  return (
    <main>
      <h1>Post: {params.slug}</h1>
    </main>
  );
}

If someone visits /blog/hello-world, the value of params.slug is "hello-world".

Diagram: How Parameters Flow

USER VISITS: /blog/learn-nextjs
               ↓
NEXT.JS READS: app/blog/[slug]/page.js
               ↓
PASSES TO COMPONENT:
params = { slug: "learn-nextjs" }
               ↓
COMPONENT USES: params.slug → "learn-nextjs"
               ↓
SHOWS: The content for that specific post

Using the Parameter to Fetch Data

The real power of dynamic routes appears when you fetch data using the parameter. Here is a practical example:

export default async function BlogPost({ params }) {
  const post = await fetch(`https://api.example.com/posts/${params.slug}`);
  const data = await post.json();

  return (
    <main>
      <h1>{data.title}</h1>
      <p>{data.body}</p>
    </main>
  );
}

Every time someone visits a different blog post URL, the same file runs but fetches different data based on the slug.

Multiple Dynamic Segments

You can have more than one dynamic segment in a URL by nesting dynamic folders.

app/shop/[category]/[product]/page.js

Matches:
/shop/electronics/iphone
/shop/clothing/blue-shirt
/shop/books/nextjs-guide

params = { category: "electronics", product: "iphone" }

Catch-All Routes

Use three dots inside the brackets to match any number of URL segments:

app/docs/[...slug]/page.js

Matches:
/docs/getting-started
/docs/api/reference
/docs/api/components/button

params.slug = ["api", "components", "button"]

Diagram: Static vs Dynamic Routes Side by Side

STATIC ROUTE:
app/about/page.js     → always shows /about page (one URL, one page)

DYNAMIC ROUTE:
app/blog/[slug]/page.js → handles /blog/ANY-VALUE (one file, many URLs)

Key Takeaway

Dynamic routes use square brackets around a folder name to capture variable URL segments. One file handles many different URLs. The captured value arrives in your component through the params object, and you use it to show the right content.

Leave a Comment