Dynamic Routes & Catch-All Segments

5 questions found

What is a dynamic route in Next.js, and how do you create one?

Beginner
A dynamic route lets a single page template handle many different URLs by using a folder name wrapped in square brackets, such as [id], which captures that part of the URL as a parameter you can use to fetch the correct data for that specific page.
// app/products/[id]/page.js
export default async function ProductPage({ params }) {
  const { id } = await params;
  const product = await getProduct(id);
  return <h1>{product.name}</h1>;
}
Real-world example An online store uses a single dynamic route to display thousands of different product pages, with each product's unique id in the URL determining which product details are shown.

Common follow-ups: How do you access the dynamic parameter value inside the page component?;Can you have multiple dynamic segments in the same route?

Routing (App/Pages Router);Data Fetching

What is a catch-all route segment, and when would you use one?

Intermediate
A catch-all segment, written with three dots inside brackets like [...slug], matches any number of URL segments after a certain point, capturing them as an array, which is useful for building things like nested category pages or a flexible content management system with arbitrarily deep URL structures.
// app/docs/[...slug]/page.js
export default async function DocsPage({ params }) {
  const { slug } = await params;
  // slug is an array, e.g. ['getting-started', 'installation']
  return <p>Viewing: {slug.join(' / ')}</p>;
}
Real-world example A documentation website uses a catch-all route to handle URLs of any depth, such as docs/getting-started/installation, all through a single flexible page template.

Common follow-ups: What is the difference between a catch-all segment and an optional catch-all segment?;How do you handle a completely invalid or missing slug in a catch-all route?

Routing (App/Pages Router);Error Handling & Not Found Pages

What is an optional catch-all route segment, and how is it different from a regular catch-all segment?

Intermediate
An optional catch-all segment, written with double brackets like [[...slug]], works just like a regular catch-all segment but also matches the base route with no additional segments at all, meaning the same page component can handle both the root path and any nested paths beneath it.
// app/shop/[[...slug]]/page.js
// Matches /shop, /shop/electronics, and /shop/electronics/phones
export default async function ShopPage({ params }) {
  const { slug } = await params;
  return <p>Category path: {slug ? slug.join('/') : 'All products'}</p>;
}
Real-world example An e-commerce site uses an optional catch-all route so the same shop page component handles both the main shop landing page and any nested category or subcategory pages beneath it.

Common follow-ups: When would you choose an optional catch-all over a required one?;How do you generate static pages ahead of time for a catch-all route?

Routing (App/Pages Router);Rendering (SSR/SSG/ISR)

How do you pre-generate static pages for dynamic routes at build time using generateStaticParams?

Advanced
You export a generateStaticParams function from your dynamic route's page file that returns an array of parameter objects, and Next.js will use these to build a separate static page for each set of parameters ahead of time, rather than waiting to generate them on demand when a user first visits.
export async function generateStaticParams() {
  const products = await getAllProducts();
  return products.map(product => ({ id: product.id }));
}

export default async function ProductPage({ params }) {
  const { id } = await params;
  const product = await getProduct(id);
  return <h1>{product.name}</h1>;
}
Real-world example An online catalog pre-builds static pages for every product at build time using generateStaticParams, giving visitors extremely fast page loads since the pages are already fully generated ahead of time.

Common follow-ups: What happens to routes not included in generateStaticParams when a user visits them?;How does this interact with Incremental Static Regeneration?

Rendering (SSR/SSG/ISR);On-Demand Revalidation Strategies

How would you handle a very large number of dynamic pages, such as millions of products, without making the build take too long?

Advanced
You use generateStaticParams to pre-build only the most important or most visited pages ahead of time, and let the remaining pages generate on demand the first time they are requested using incremental static regeneration, caching them afterward so future visitors get the fast, pre-built version.
export async function generateStaticParams() {
  const topProducts = await getTopProducts(1000);
  return topProducts.map(p => ({ id: p.id }));
}

export const dynamicParams = true; // allow other ids to generate on demand
Real-world example A massive online marketplace with millions of listings only pre-builds its most popular thousand product pages at build time, letting the rest generate on their first visit and stay cached afterward.

Common follow-ups: What does the dynamicParams setting control in this scenario?;How do you decide which pages are important enough to pre-build?

Rendering (SSR/SSG/ISR);Caching