Chau Tech Diary

Checking Chau's online status

Back to Blog

    Understanding Catch-All Segments in Next.js

    Next.js is well-known for its intuitive file-based routing system. One of the most powerful features of that system is the catch-all segment.

    In this article, we’ll break down what catch-all segments are, how to use them, and what common mistakes to avoid.


    🧠 What Is a Catch-All Segment?

    A catch-all segment is a dynamic route in Next.js that matches any number of path segments.

    For example:

    /pages/docs/[...slug].tsx

    This single file will match:

    • /docs
    • /docs/getting-started
    • /docs/guides/setup/windows

    The key is the [...] syntax. It tells Next.js to capture everything after the base path and store it as an array.


    🔍 Accessing the Segments

    When you define a catch-all route, the matched segments are passed into the page’s params.

    export default function Page({ params }) {
      return <div>{JSON.stringify(params.slug)}</div>;
    }

    If the URL is /docs/guides/setup, params.slug will be:

    ["guides", "setup"]

    🎯 Optional Catch-All Segments

    You can also make the segment optional:

    /pages/docs/[[...slug]].tsx

    This matches:

    • /docs
    • /docs/anything/here
    • /docs/even/deeper/paths

    The extra [] around the spread tells Next.js this route should also match the base path.


    🛠️ Use Cases for Catch-All Segments

    Catch-all segments are perfect for:

    • Documentation pages
    • Blog categories and nested slugs
    • CMS-powered routes
    • User-generated URLs (e.g. forums, multi-tenant apps)

    🧪 Example: CMS-Powered Blog

    Let’s say your CMS provides blog paths like:

    • /blog/tech/javascript
    • /blog/tech/react/hooks
    • /blog/lifestyle/productivity

    Create a catch-all route:

    /pages/blog/[...slug].tsx

    You can now use the slug array to load the appropriate content.

    const path = params.slug.join('/');
    const post = await fetchPostByPath(path);

    🧱 Table: [slug] vs [...slug] vs [[...slug]]

    Route SegmentMatchesSlug Result
    [slug]/blog/react"react"
    [...slug]/blog/react/hooks["react", "hooks"]
    [[...slug]]/blog and deeperundefined or array

    ❗ Common Mistakes to Avoid

    “Catch-all segments are powerful, but easy to misuse.”

    ⚠️ Mistake 1: Using [slug] instead of [...slug]

    [slug] only matches a single segment. If you need to match nested paths, you need the spread syntax.

    ⚠️ Mistake 2: Not checking for undefined

    If you're using [[...slug]], remember that params.slug can be undefined.


    📚 Related Reading


    🧾 Summary

    • Catch-all segments let you match multiple path segments using [...slug].
    • Optional segments use [[...slug]] and match the base path too.
    • You can build powerful CMS, docs, and multi-level apps with this feature.
    • Be mindful of how you handle undefined and path depth.

    Catch-all routing diagram

    Thanks for reading!