Careeroza
Catch-all Segments
[...slug]
Three dots catch one or more segments as an array. app/docs/[...slug]/page.tsx:
| URL | params |
|---|---|
/docs/shipping | { slug: ['shipping'] } |
/docs/returns/refunds/upi | { slug: ['returns', 'refunds', 'upi'] } |
/docs | 404 (needs at least one segment) |
export default async function DocsPage({ params }: { params: Promise<{ slug: string[] }> }) {
const { slug } = await params;
return <h1>Help: {slug.join(' / ')}</h1>;
}How Matching Works
Example
A small route matcher that supports static parts, [id] and [...slug]. Next.js does the same, with static routes winning over dynamic ones.
type Params = Record<string, string | string[]>;
function match(pattern: string, path: string): Params | null {
const want = pattern.split('/').filter(Boolean);
const got = path.split('/').filter(Boolean);
const params: Params = {};
for (let i = 0; i < want.length; i++) {
const seg = want[i];
if (seg.startsWith('[...')) {
const rest = got.slice(i);
if (rest.length === 0) return null;
params[seg.slice(4, -1)] = rest;
return params;
}
if (got[i] === undefined) return null;
if (seg.startsWith('[')) params[seg.slice(1, -1)] = got[i];
else if (seg !== got[i]) return null;
}
return want.length === got.length ? params : null;
}
const routes = ['/products/new', '/products/[id]', '/docs/[...slug]'];
for (const url of ['/products/new', '/products/42', '/docs/returns/upi', '/docs', '/cart']) {
const hit = routes.map((r) => [r, match(r, url)] as const).find(([, p]) => p !== null);
console.log(url.padEnd(20), hit ? hit[0] + ' ' + JSON.stringify(hit[1]) : '404');
}Output
/products/new /products/new {}
/products/42 /products/[id] {"id":"42"}
/docs/returns/upi /docs/[...slug] {"slug":["returns","upi"]}
/docs 404
/cart 404