·9 min read

How to Create Dynamic Routes in Next.js App Router

Dynamic routing is a backbone feature in modern web applications, allowing tailored content delivery and sophisticated user experiences. For developers growing with the React ecosystem, Next.js stands out for its file-system-based routing, and with the introduction of the App Router, creating dynamic routes has never been more seamless. If you’re looking to learn how to create dynamic routes in Next.js App Router, you’re in the right place. This guide unpacks everything you need—step by step.

Why Dynamic Routes Matter in Next.js

Dynamic routes power the web’s most engaging applications. Imagine platforms like e-commerce sites, social networks, or news portals. Their URLs aren’t static; each user, product, or article needs a unique path—yet all must use consistent templates. Thanks to dynamic routes, you can efficiently deliver personalized content at scale.

Next.js, particularly since version 13 and onward, introduced the App Router to replace the Pages Router. This evolution emphasizes both flexibility and performance—core values when managing dynamic routes in Next.js with the App Router paradigm.

Understanding the App Router in Next.js

The App Router is Next.js’s new approach to routing, leveraging the /app directory. Unlike older versions that used /pages, the App Router provides more powerful layouts, server components, and enhanced data fetching. This modern routing model is especially impactful for implementing dynamic routes.

Key Features of the App Router

  • Segment-based routing: Directories and files determine URL structure.
  • Dynamic segments: Enable the creation of routes parameterized by variables.
  • Server and client components: Improved control over rendering and hydration.

Before discussing how to create dynamic routes in Next.js App Router, let’s ground ourselves in the fundamental directory structure.

Setting Up Your Next.js Project

First, ensure you’re using Next.js 13 or higher, as the App Router and related conventions are not available in older releases.

npx create-next-app@latest my-dynamic-routes-project
cd my-dynamic-routes-project

When prompted, enable the experimental App Router feature or opt for the /app directory structure.

Anatomy of Dynamic Routes in Next.js App Router

Dynamic routes in Next.js App Router use a bracket syntax. For example, to display a blog post by slug, you might set up your directory as:

/app
  /blog
    [slug]
      page.js

In this example, [slug] acts as a placeholder, capturing any value in that segment of the URL, such as /blog/my-first-post.

Creating a Dynamic Route Segment

  1. Inside /app directory: Create a new folder for your top-level route (e.g., blog).
  2. Add a dynamic segment: Make a subfolder named with brackets (e.g., [slug]).
  3. Create a page file: Inside the dynamic segment directory, create a page.js or page.tsx file.

Here’s a code sample for /app/blog/[slug]/page.js:

import { use } from "react";
 
export default function BlogPost({ params }) {
  const { slug } = params;
 
  // Fetch data based on slug
  // For example, use fetch or a third-party SDK
 
  return (
    <main>
      <h1>Blog Post: {slug}</h1>
      {/* Actual content here */}
    </main>
  );
}

Incorporating how to create dynamic routes in Next.js App Router in this fashion unlocks rich, user-specific content delivery.

Advanced Dynamic Routing Scenarios

Catch-All Routing

There are cases when you need routes that handle unknown or multiple nested segments—for example, documentation sites or complex navigation trees. Next.js App Router supports catch-all routes through ellipsis syntax:

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

The [...slug] segment captures any combination of segments, letting you programmatically respond to requests like /docs/getting-started/installation.

export default function Docs({ params }) {
  const { slug } = params;
  const path = Array.isArray(slug) ? slug.join("/") : slug;
 
  return (
    <main>
      <h1>Docs Path: {path}</h1>
      {/* Render docs based on path */}
    </main>
  );
}

Optional Catch-All Routes

Sometimes, the catch-all parameter might not exist in the URL. For these instances, use the double bracket syntax:

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

This lets /docs, /docs/getting-started, and even /docs/getting-started/installation resolve to the same page component, with the parameter being optional.

Nested Dynamic Segments

For even more granular routing, nest multiple dynamic segments:

/app
  /users
    [userId]
      /posts
        [postId]
          page.js

With this, routes like /users/123/posts/456 become possible, maximizing the routing flexibility of your application.

Data Fetching with Dynamic Routes

One of the biggest advantages of Next.js's App Router is how it consolidates routing with data fetching. There are several strategies:

1. Fetching on the Server

When using server components (the default in the App Router), Next.js encourages fetching data directly within your page.js:

// /app/products/[productId]/page.js
export default async function ProductPage({ params }) {
  const { productId } = params;
  const product = await fetch(
    `https://api.example.com/products/${productId}`
  ).then((res) => res.json());
 
  return (
    <section>
      <h1>{product.name}</h1>
      <p>{product.description}</p>
    </section>
  );
}

This approach yields blazing fast response times and improved SEO, as the content is rendered on the server before reaching the user.

2. Client-Side Fetching

If you need interactive data, you can still fetch on the client:

"use client";
import { useEffect, useState } from "react";
 
export default function ProductClientPage({ params }) {
  const { productId } = params;
  const [product, setProduct] = useState(null);
 
  useEffect(() => {
    async function fetchProduct() {
      const res = await fetch(`/api/products/${productId}`);
      const data = await res.json();
      setProduct(data);
    }
    fetchProduct();
  }, [productId]);
 
  if (!product) return <div>Loading...</div>;
 
  return (
    <section>
      <h1>{product.name}</h1>
      <p>{product.description}</p>
    </section>
  );
}

Client components enable user-driven data updates and interactivity, complementing dynamic route rendering.

SEO Benefits of Dynamic Routes in Next.js App Router

Learning how to create dynamic routes in Next.js App Router isn’t just about developer ergonomics—it’s central to SEO success. Properly structured dynamic routes mean:

  • Descriptive, crawlable URLs: Search engines love clean, semantic, and keyword-rich URLs, which dynamic routing naturally produces.
  • Server-side rendering (SSR): Next.js fetches and serves content server-side, ensuring search bots see the same robust content as users.
  • Meta tags per page: Each route (dynamic or static) can have its unique metadata, crucial for ranking and social sharing.

For instance, Next.js App Router encourages use of the generateMetadata function to inject meta tags dynamically:

export async function generateMetadata({ params }) {
  const { slug } = params;
  // Fetch or compute meta info here
  return {
    title: `${slug} | My Blog`,
    description: `Read more about ${slug} on My Blog.`,
  };
}

Adoption of Next.js, and specifically its App Router, is surging among industry leaders. Vercel (the company behind Next.js) emphasizes that flexible routing structures are core to unlocking developer productivity and site performance. Numerous major commerce and media brands publicly use dynamic routes in Next.js for everything from product pages to user-generated content.

Industry expert Guillermo Rauch, Vercel CEO, highlights the evolution:
"The App Router paradigm is about bringing the power of server components and fine-grained routing control together for faster and more maintainable apps."

As routing requirements grow in complexity, mastering how to create dynamic routes in Next.js App Router is quickly transitioning from a nice-to-have skill to an essential one.

Best Practices for Scalable Dynamic Routing

Dynamic routing in Next.js App Router brings power—but leveraging it at scale requires some strategy:

1. Modularize Route Components

Keep route components focused. For example, if multiple routes display user profiles, abstract profile rendering into a shared component.

2. Use Loading and Error Boundaries

Next.js App Router supports special loading.js and error.js files in route segments. Use them to show helpful loading spinners or error instructions:

/app
  /blog
    [slug]
      loading.js
      error.js

3. Pre-Fetch and Pre-Generate Where Possible

Use generateStaticParams to statically generate common dynamic routes at build time for super-fast loads:

export async function generateStaticParams() {
  const posts = await fetchPosts(); // get post slugs, for example
  return posts.map((post) => ({ slug: post.slug }));
}

Next.js will pre-render these dynamic routes, combining dynamic flexibility with static performance.

4. Security and Validation

Always validate parameters from dynamic routes. Sanitize inputs before fetching from APIs or databases to avoid attacks.

5. Analytics and Tracking

Implement route-aware analytics. Track which dynamic routes receive the most traffic and optimize accordingly.

Common Pitfalls & How to Avoid Them

Even seasoned developers can stumble when they first create dynamic routes in Next.js App Router. Here are a few frequent issues:

  • Misnaming dynamic segments: Ensure bracketed folder names match the expected parameter in the route.
  • Forgetting to catch all intended paths: Use catch-all segments when the depth of routes varies.
  • Missing SSR data functions: Leverage async data fetching in server components to avoid client-only delays.

Migration: Pages Router to App Router

If your project started on the legacy /pages router, migrating to /app and updating dynamic routes is straightforward:

  • In /pages, you might find [slug].js.
  • In /app, move this to /app/[slug]/page.js.

Be sure to adapt code to support new file-based conventions, and test with expected dynamic paths.

Unlocking the Future with Dynamic Routes

Mastering how to create dynamic routes in Next.js App Router isn’t just about technical ability—it empowers faster iteration, superior user experience, and robust SEO. The App Router’s segment-based file system, enriched with server and client component options, puts full routing control back into the developer’s hands.

Key Takeaways:

  • Embrace dynamic segment naming ([param], [...param], [[...param]]) for flexible routes.
  • Combine server and client components to balance SEO with interactivity.
  • Leverage advanced data fetching, metadata generation, and error handling for professional-grade applications.

As Next.js continues to advance, the App Router paradigm will shape the future of React application routing. By learning how to create dynamic routes in Next.js App Router, you’re not just keeping up—you’re leading the way in modern web development.

By fully grasping how to create dynamic routes in Next.js App Router, developers position themselves for scalable growth and top-tier performance in every app they build. The future of web routing is dynamic—make it yours today!

More Posts