Back to results for “Routing (App/Pages Router)”
Next.js › Dynamic Routes & Catch-All Segments

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

Intermediate

Answer

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?