Dynamic Routes ([id]), Catch-All Routes ([...slug]) & Route Groups ((group))0%
Streaming UI with loading.tsx and Suspense Boundaries

Dynamic Routes ([id]), Catch-All Routes ([...slug]) & Route Groups ((group))

Beginner12 min read•Updated: Jul 11, 2026
Study MaterialsCheatsheet

Dynamic Routes ([id]), Catch-All Routes ([...slug]) & Route Groups ((group))

In the Next.js App Router, advanced routing patterns are defined using folder naming syntax: Square Brackets [param] for dynamic segments, Ellipses [...slug] for catch-all routes, and Parentheses (group) for organizing code without affecting the URL path.


1. Dynamic Route Segments: [param]

When a URL segment is dynamic (such as a blog post slug or user ID):

  • Folder: app/blog/[slug]/page.tsx
  • URL: /blog/learn-nextjs -> { slug: 'learn-nextjs' }
TSX
// app/blog/[slug]/page.tsx
interface PageProps {
params: Promise<{ slug: string }>;
}
 
export default async function BlogPost({ params }: PageProps) {
// In Next.js 15, params is an asynchronous Promise!
const { slug } = await params;
 
return (
<article className="max-w-3xl mx-auto py-8">
<h1 className="text-3xl font-bold">Article: {slug}</h1>
</article>
);
}

2. Catch-All & Optional Catch-All Routes

1. Catch-All: [...slug]

Matches any number of subsequent path segments and returns them as a string array:

  • Folder: app/docs/[...slug]/page.tsx
  • Matches: /docs/getting-started -> { slug: ['getting-started'] }
  • Matches: /docs/api/v2/authentication -> { slug: ['api', 'v2', 'authentication'] }
  • Does NOT match /docs itself.

2. Optional Catch-All: [[...slug]] (Double Brackets)

Matches all sub-segments AND matches the parent route itself:

  • Matches: /docs -> { slug: undefined }
  • Matches: /docs/components/button -> { slug: ['components', 'button'] }

3. Route Groups: (groupName)

Route Groups allow organizing folders and sharing specific layouts without affecting the URL path:

Output
app/
├── (marketing)/
│ ├── layout.tsx # Marketing layout (Hero header, pricing navbar)
│ ├── about/page.tsx -> URL: /about
│ └── pricing/page.tsx -> URL: /pricing
└── (dashboard)/
├── layout.tsx # Authenticated layout (Sidebar, profile dropdown)
└── analytics/page.tsx -> URL: /analytics

Notice that neither (marketing) nor (dashboard) appears in the browser URL!


Interactive Quiz

Multiple Choice Questions

Question 1
In Next.js 15, how should route params and search searchParams be consumed inside an async Server Component page.tsx?
Question 2
Which folder naming pattern matches both /shop AND any deeply nested path like /shop/clothing/jackets/winter?
Question 3
What is the primary purpose of Route Groups named with parentheses, such as app/(auth)/login/page.tsx?
Question 4
Given the route app/tutorials/[...slug]/page.tsx, what will (await params).slug evaluate to when a user visits /tutorials/web/react/hooks?
Question 5
What happens if two different Route Groups define the same URL path (e.g. (marketing)/about/page.tsx and (admin)/about/page.tsx)?

Next Lesson

Streaming UI with loading.tsx and Suspense Boundaries

Continue learning with hands-on practice, examples, and exercises in the upcoming topic.

Practice Quiz

Test your understanding of this lesson with 5 questions. Each question has one correct answer.

PrevNext