Next.js Lesson 9: Dynamic Routes & Params
Dynamic routes let one page template serve thousands of different URLs — /blog/any-post, /users/anyone, /products/anything.
Dynamic Segments
// [param] = single dynamic segment
app/blog/[slug]/page.tsx → /blog/hello-world
app/users/[id]/page.tsx → /users/42
// [...segments] = catch-all
app/docs/[...path]/page.tsx → /docs/a/b/c
// [[...segments]] = optional catch-all
app/shop/[[...filters]]/page.tsx → /shop, /shop/category, /shop/cat/size
Accessing Params
// app/blog/[slug]/page.tsx
interface PageProps {
params: { slug: string };
searchParams: { [key: string]: string | undefined };
}
async function BlogPost({ params, searchParams }: PageProps) {
const { slug } = params;
const page = searchParams.page || "1";
const post = await fetchPost(slug);
// Generate metadata dynamically
// (in generateMetadata function)
return (
<article>
<h1>{post.title}</h1>
<p>{post.content}</p>
</article>
);
}
Dynamic Metadata
// Generate SEO metadata based on the dynamic route
export async function generateMetadata({ params }: PageProps) {
const post = await fetchPost(params.slug);
return {
title: post.title,
description: post.excerpt,
openGraph: {
title: post.title,
description: post.excerpt,
images: [post.image]
}
};
}
🏋️ Practice Task
Build a course lesson viewer: /courses/[course]/lessons/[id]. Show course name and lesson id from params. Generate metadata with the lesson title. Add breadcrumb navigation: Courses → [course] → Lesson [id]. Fetch mock data from an object (no real API).
💡 Hint: const lessonData = { python: { 1: “Variables”, 2: “Functions” } }. Access: lessonData[params.course]?.[params.id]