File-based routing is the foundation of both Next.js routers: your folder structure defines your URL structure. This lesson focuses on how that mapping works in detail, using the App Router as the primary example.
Folders Define URL Segments
In the App Router, every folder inside app/ represents one segment of a URL path. A folder named blog inside app/ contributes the /blog segment; a folder named [slug] inside app/blog/ contributes a dynamic segment, matching any value at that position in the URL, like /blog/hello-world.
A folder only becomes an actual, navigable route once it contains a page.tsx (or, for APIs, a route.ts) file. Folders without one of these files can still exist purely for organization — for example, to hold a shared layout.tsx or colocated components — without adding a new URL.
Folder names become URL segments; only folders with a page.tsx become visitable routes, and underscore-prefixed folders are excluded from routing entirely.
Naming Conventions That Affect Routing
[slug] // dynamic segment: /blog/hello-world
[...slug] // catch-all segment: /docs/a/b/c
[[...slug]] // optional catch-all: matches /docs too
(marketing) // route group: organizes without adding a URL segment
_components // private folder: excluded from routing entirely
Square brackets [name] create a dynamic segment accessible via params.name.
Three dots inside brackets [...name] create a catch-all segment matching multiple path parts.
Double brackets around a catch-all [[...name]] make that segment optional.
Parentheses (name) create a route group that organizes files without affecting the URL.
File-Based Routing Cheat Sheet
How different folder and file names map to routing behavior.
Pattern
Example Path
Matches
about/page.tsx
app/about/page.tsx
/about
[id]/page.tsx
app/posts/[id]/page.tsx
/posts/123
[...slug]/page.tsx
app/docs/[...slug]/page.tsx
/docs/a/b/c
[[...slug]]/page.tsx
app/docs/[[...slug]]/page.tsx
/docs and /docs/a/b
(group)/page.tsx
app/(marketing)/about/page.tsx
/about (group is invisible in URL)
_folder/
app/_lib/helpers.ts
Not routable at all
Reading Route Parameters
Every dynamic segment is available to a page.tsx component through its params prop, which Next.js provides automatically. Catch-all segments are delivered as an array of strings rather than a single string.
For /blog/hello-world, params.slug is the string "hello-world".
Colocating Non-Route Files Safely
Because only page.tsx and route.ts are treated as routable, you can safely colocate components, tests, styles, and utility files anywhere inside app/ without accidentally creating new URLs — as long as you avoid naming them exactly page.tsx or route.ts.
app/blog/PostCard.tsx — a component, not a route.
app/blog/utils.ts — a helper file, not a route.
app/blog/_internal/ — a private folder, explicitly excluded from routing.
Common Mistakes
Naming a component file page.tsx by accident and creating an unintended route.
Forgetting that catch-all segments ([...slug]) deliver an array, not a string, in params.
Assuming route groups (name) show up in the URL — they are intentionally invisible.
Placing shared utilities directly in app/ without an underscore prefix, risking accidental route creation later.
Key Takeaways
Folders inside app/ map directly to URL segments; page.tsx is what makes a segment routable.
[name] creates dynamic segments; [...name] creates catch-all segments; [[...name]] makes them optional.
Route groups (name) organize files without changing the URL structure.
Underscore-prefixed folders (_lib, _components) are excluded from routing entirely.
Non-special files can be colocated freely inside route folders without becoming routes themselves.
Pro Tip
Adopt a naming convention early — for example, always prefixing non-route helper folders with an underscore — so that as your app/ directory grows, it stays obvious at a glance which folders are real routes and which are just organizational.
You now understand how files map to routes. Next, look at overall project structure conventions for organizing a larger Next.js application.