Catch-all Segments

Use [...slug] to match any number of path segments in a single route.

Syntaxapp/docs/[...slug]/page.tsx

A catch-all segment, written [...slug], matches one or more segments and collects them into an array. It is useful for docs sites or any deeply nested, data-driven structure.

Variants

  • [...slug] — matches /docs/a, /docs/a/b, etc. (one or more).
  • [[...slug]]optional catch-all, also matches the base /docs.

Example

Example · typescript
// app/docs/[...slug]/page.tsx
// /docs/a/b/c  ->  slug = ['a', 'b', 'c']
export default async function Docs({
  params,
}: {
  params: Promise<{ slug: string[] }>;
}) {
  const { slug } = await params;
  return <p>Path: {slug.join(' / ')}</p>;
}

When to use it

  • A documentation site uses [...path] to handle arbitrarily deep URLs like /docs/api/v2/endpoints.
  • A CMS-driven site maps any URL to a page-builder template using a catch-all route at the root.
  • An optional catch-all [[...slug]] makes the index page and all its children share a single route file.

More examples

Catch-all folder structure

The [...slug] folder matches one or more path segments and collects them into an array.

Example · bash
app/
└── docs/
    └── [...slug]/
        └── page.tsx   # matches /docs, /docs/a, /docs/a/b ...

Reading catch-all params

The slug param is a string array, so joining it reconstructs the full path for data fetching.

Example · ts
// app/docs/[...slug]/page.tsx
type Props = { params: Promise<{ slug: string[] }> };

export default async function DocsPage({ params }: Props) {
  const { slug } = await params;
  const path = slug.join('/');
  return <h1>Docs path: {path}</h1>;
}

Optional catch-all segment

Double brackets make the segment optional, so the same file handles both / and /any/deep/path.

Example · ts
// app/[[...slug]]/page.tsx
type Props = { params: Promise<{ slug?: string[] }> };

export default async function Page({ params }: Props) {
  const { slug } = await params;
  if (!slug) return <h1>Home</h1>;
  return <h1>Path: {slug.join('/')}</h1>;
}

Discussion

  • Be the first to comment on this lesson.