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].tsxThis 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]].tsxThis 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].tsxYou 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 Segment | Matches | Slug Result |
|---|---|---|
[slug] | /blog/react | "react" |
[...slug] | /blog/react/hooks | ["react", "hooks"] |
[[...slug]] | /blog and deeper | undefined 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.

Thanks for reading!