Skip to content
Watch the complete Next.js 15 course on YouTube

Catch-all segments

This page explains how to create routes that can handle any number of URL segments in Next.js.

Understanding catch-all segments

While nested dynamic routes handle routes with multiple segments, they become cumbersome when dealing with variable-depth URLs. Consider a documentation site with routes defined by features and concepts.

  • Directoryapp/
    • Directorydocs/
      • page.tsx /docs
      • Directory[feature]/
        • page.tsx /docs/feature-1
        • Directory[concept]/
          • page.tsx /docs/feature-1/concept-1
      • Directory[tutorials]/
        • page.tsx /docs/tutorials
        • Directory[tutorial]/
          • page.tsx /docs/tutorials/tutorial-1
      • Directory[reference]/
        • page.tsx /docs/reference
        • Directory[concept]/
          • page.tsx /docs/reference/concept-1

With nested dynamic routes, you would need to create a new route for each feature, tutorial, and reference section. And you’d be doing that for a page that has the same user interface across the board. Only the content would change.

Catch-all segments are an extension of dynamic routes that can capture multiple URL segments.

Creating catch-all segments

To create a catch-all segments route in Next.js:

  1. Create a folder with square brackets and ellipses before the folder name (e.g., [...slug])
  2. Add a page.tsx file inside this folder
  3. Next.js will map any number of segments to this page component
  • Directoryapp/
    • Directorydocs/
      • Directory[…slug]/
        • page.tsx Matches /docs/any/number/of/segments

Here’s a basic catch-all route component:

app/docs/[...slug]/page.tsx
export default async function Doc({
params,
}: {
params: Promise<{ slug: string[] }>;
}) {
const { slug } = await params;
return <h1>Viewing path: {slug.join("/")}</h1>;
}

The slug parameter is an array of all segments captured in the URL.

For example:

  • URL /docs/intro/setupparams.slug = ["intro", "setup"]
  • URL /docs/advanced/config/optionsparams.slug = ["advanced", "config", "options"]
  • URL /docs/tutorials/build-a-blogparams.slug = ["tutorials", "build-a-blog"]
  • URL /docs/reference/use-cacheparams.slug = ["reference", "use-cache"]

How catch-all segments route works

When you create a folder with ellipses and square brackets [...slug], Next.js treats it as a catch-all segment.

  • /docs/intro or /docs/advanced/config/options or /docs/any/number/of/segments is handled by the same component in app/docs/[...slug]/page.tsx
  • The slug parameter is an array containing all path segments. You need to await it and access the segments by their index.

Optional catch-all segments

For routes that should also match their root path, use double brackets as part of the folder name:

  • Directoryapp/
    • Directorydocs/
      • Directory[[…slug]]/
        • page.tsx /docs and /docs/any/path

The double brackets indicate that segments are optional. Without the double brackets, /docs will render a 404 page.

Catch-all routes are particularly useful for:

  • Documentation sites
  • CMS content with dynamic paths
  • File system viewers
  • Any content with variable-depth hierarchies

Good to know

  • Catch-all routes have lower priority than fixed routes
  • They must catch ALL remaining segments (can’t have fixed routes after)
  • The params are always provided as an array, even for single segments