Topic 05 / 13

Dynamic Routes & generateStaticParams

~9 min read  //  Next.js Series  //  Coding India

Dynamic Segments

Square brackets make a folder dynamic:

app/
└── blog/
    ├── page.js              # /blog
    └── [slug]/
        └── page.js          # /blog/anything
// app/blog/[slug]/page.js
import { notFound } from "next/navigation";

export default async function PostPage({ params }) {
  const { slug } = await params;            // params is async in Next 15
  const post = await getPost(slug);

  if (!post) notFound();                    // renders the closest not-found.js

  return (
    <article>
      <h1>{post.title}</h1>
      <div dangerouslySetInnerHTML={{ __html: post.html }} />
    </article>
  );
}

searchParams — Query Strings

// /courses?track=django&page=2
export default async function CoursesPage({ searchParams }) {
  const { track = "all", page = "1" } = await searchParams;
  const courses = await getCourses(track, Number(page));
  ...
}

Reading searchParams makes the route dynamic — expected, since the URL varies per request.

generateStaticParams — Pre-Build Known Pages

For content you can enumerate (blog posts, products, tutorial topics), build every page ahead of time — each URL becomes static HTML on the CDN:

// app/blog/[slug]/page.js
export async function generateStaticParams() {
  const posts = await getAllPosts();
  return posts.map(post => ({ slug: post.slug }));
  // → builds /blog/first-post, /blog/second-post, …
}

Pair with revalidate and new posts appear without redeploying. Slugs not returned are rendered on first request by default (control with export const dynamicParams = false to 404 instead).

Catch-All Routes

app/docs/[...parts]/page.js     # /docs/a, /docs/a/b/c — parts = ['a','b','c']
app/shop/[[...filters]]/page.js # optional: ALSO matches /shop itself

Useful for docs trees and filter UIs where depth varies.

Linking It Together

// the listing page links into the dynamic route
{posts.map(post => (
  <Link key={post.slug} href={`/blog/${post.slug}`}>
    {post.title}
  </Link>
))}

The Pattern to Internalise

List page (/blog) + detail page (/blog/[slug]) + generateStaticParams + revalidate is the canonical Next.js content architecture — it powers blogs, shops, docs sites, and course platforms like this one. Master this one pattern and most content sites are routine.