File-Based Routing Deep Dive
Next.js uses the file system as the source of truth for routes. Understanding the conventions unlocks powerful routing patterns.
Basic Routes
Folders define route segments. A page.tsx inside makes it accessible:
app/
โโโ page.tsx โ /
โโโ about/
โ โโโ page.tsx โ /about
โโโ blog/
โ โโโ page.tsx โ /blog
โโโ contact/
โโโ page.tsx โ /contact
Dynamic Routes
Use square brackets for dynamic segments:
app/
โโโ blog/
โ โโโ [slug]/
โ โโโ page.tsx โ /blog/my-first-post
โโโ users/
โ โโโ [id]/
โ โโโ page.tsx โ /users/123
Access parameters in your component:
// app/blog/[slug]/page.tsx
export default async function BlogPost({
params,
}: {
params: Promise<{ slug: string }>
}) {
const { slug } = await params
return <h1>Post: {slug}</h1>
}
Catch-All Routes
Use [...slug] to catch multiple segments:
app/
โโโ docs/
โโโ [...slug]/
โโโ page.tsx โ /docs/a, /docs/a/b, /docs/a/b/c
// params.slug = ['a', 'b', 'c'] for /docs/a/b/c
export default async function Docs({
params,
}: {
params: Promise<{ slug: string[] }>
}) {
const { slug } = await params
return <div>Path: {slug.join('/')}</div>
}
Use [[...slug]] for optional catch-all (also matches the root):
app/
โโโ shop/
โโโ [[...categories]]/
โโโ page.tsx โ /shop, /shop/clothes, /shop/clothes/shirts
Static Params Generation
For dynamic routes, tell Next.js which pages to pre-generate:
// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
const posts = await getPosts()
return posts.map((post) => ({
slug: post.slug,
}))
}
Colocation
You can colocate files that aren't special (page, layout, etc.):
app/
โโโ dashboard/
โโโ page.tsx # The route
โโโ Dashboard.tsx # Component (not a route)
โโโ dashboard.css # Styles
โโโ utils.ts # Helpers
Only page.tsx, layout.tsx, and other special files affect routing.
Private Folders
Prefix with underscore to exclude from routing:
app/
โโโ _components/ # Shared components (not routes)
โ โโโ Button.tsx
โโโ _lib/ # Utilities (not routes)
โ โโโ api.ts
โโโ dashboard/
โโโ page.tsx # Actual route
Route Priority
When routes could conflict, Next.js uses this priority:
- Static routes (
/about) - Dynamic routes (
/[slug]) - Catch-all routes (
/[...slug])
app/
โโโ blog/
โ โโโ page.tsx # /blog (static, wins)
โ โโโ latest/
โ โ โโโ page.tsx # /blog/latest (static, wins)
โ โโโ [slug]/
โ โโโ page.tsx # /blog/anything-else (dynamic)
Summary
- Folders define routes,
page.tsxmakes them accessible [param]for single dynamic segments[...param]for catch-all,[[...param]]for optional catch-allgenerateStaticParamspre-generates dynamic routes- Underscore prefix (
_folder) excludes from routing - Static routes take priority over dynamic ones
Up next ยท Lesson 3 of 26
Server vs Client Components
3 min read
2 of 26 lessons done

