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
- page.tsx
- page.tsx
Directory[tutorials]/
- page.tsx
/docs/tutorials
Directory[tutorial]/
- page.tsx
/docs/tutorials/tutorial-1
- page.tsx
- page.tsx
Directory[reference]/
- page.tsx
/docs/reference
Directory[concept]/
- page.tsx
/docs/reference/concept-1
- page.tsx
- page.tsx
- page.tsx
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:
- Create a folder with square brackets and ellipses before the folder name (e.g.,
[...slug]
) - Add a
page.tsx
file inside this folder - 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:
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/setup
→params.slug = ["intro", "setup"]
- URL
/docs/advanced/config/options
→params.slug = ["advanced", "config", "options"]
- URL
/docs/tutorials/build-a-blog
→params.slug = ["tutorials", "build-a-blog"]
- URL
/docs/reference/use-cache
→params.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 inapp/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