Optional Catch-all ([[...slug]])

Catch-all routes that don't crash on the root path.

Next.js4 min readConcept 16 of 65

The double brackets

An Optional Catch-all route uses double square brackets: [[...slug]].

It behaves exactly like a standard Catch-all route ([...slug]), capturing any number of nested URL segments into an array. However, it has one major superpower: it makes the segments *optional*.

Consolidating routes

With a standard [...slug], if a user navigates to the root folder (e.g., /docs), Next.js throws a 404 error because it requires at least one parameter.

To fix that, developers used to create two files: app/docs/page.tsx (for the root) and app/docs/[...slug]/page.tsx (for everything else). Optional Catch-all routes let you handle both scenarios in a single file.

Checking for undefined

When a user visits the root path of an Optional Catch-all route, the params object won't contain the dynamic key.

For example, in Next.js 15, if you have app/docs/[[...slug]]/page.tsx and the user visits /docs, after you await params, the slug variable will evaluate to undefined.

The Root Bypass

Review the diagram contrasting a standard Catch-all with an Optional Catch-all. Notice how the double brackets gracefully handle the root path by injecting undefined instead of throwing a 404.

Standard Catch-all

app/docs/[...slug]

Visits /docs/intro
slug:["intro"]
Visits /docs
404 Not Found (Requires ≥ 1 segment)

Optional Catch-all

app/docs/[[...slug]]

Visits /docs/intro
slug:["intro"]
Visits /docs
slug:undefined

An Optional Catch-all (double brackets) serves two routes simultaneously: the nested paths AND the root path itself.

const { slug = [] } = await params;
// By providing an empty array fallback = [], you prevent
// crashes when the user visits the root path and slug is undefined.

Check yourself

Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.

  1. 1If your route is app/docs/[[...slug]]/page.tsx, what is the value of 'slug' when a user visits exactly /docs?
  2. 2What is the safest way to destructure the params object in an Optional Catch-all route to avoid crashes?

Remember this

  • Optional catch-all routes use double brackets: [[...slug]].
  • They match deeply nested segments AND the root folder itself.
  • If matched at the root, the parameter value will be undefined.
  • Always provide a fallback (like slug = []) to prevent runtime crashes.

Done with this concept?

Mark it complete to track your progress. No login needed.