1 · Why File-Based Routing?
Traditional React apps rely on code-driven routers (e.g., React Router). Next.js flips the model: your filesystem is the router. This approach offers:
-
Zero configuration—drop a file, get a route.
-
Conventions over configuration—team-wide consistency.
-
Colocation—components, tests, and styles live next to the page that uses them. nextjs.org
2 · Anatomy of the App Router
Inside the app/
directory (introduced in Next.js 13 and stable in 15) every folder and “special file” has a role:
File / Folder | Purpose |
---|---|
app/page.js |
Home route / |
app/blog/page.js |
/blog |
app/blog/[slug]/page.js |
Dynamic route /blog/:slug |
layout.js |
Wraps all sibling routes with shared UI |
loading.js |
Instant loading skeletons while data streams |
error.js |
Route-specific error UI |
route.js |
Route Handler (API/edge) for that segment |
Only page.js
(UI) and route.js
(API) are publicly addressable; everything else is just for composition. nextjs.orgnextjs.org
Folder = “segment”
A segment is one level of the URL path. Nest folders to build deeper paths:
app/
├─ dashboard/
│ ├─ layout.js
│ ├─ page.js → /dashboard
│ └─ settings/
│ └─ page.js → /dashboard/settings
<Outlet>
boilerplate. nextjs.org3 · Dynamic Routes
Place the segment name in square brackets to capture a param:
Pattern | Example path | Params object |
---|---|---|
[id]/page.js |
/post/42 |
{ id: '42' } |
[...slug]/page.js |
/docs/guides/setup |
{ slug: ['guides','setup'] } |
[[...slug]]/page.js |
/ or any depth |
Optional catch-all |
Dynamic segments pair naturally with data fetching in Server Components or Route Handlers. nextjs.org
4 · Route Groups & Colocation
Need to group files without affecting the URL? Wrap the folder name in parentheses:
app/
└─ (marketing)/
└─ about/
└─ page.js → URL is simply /about
This keeps /about
clean while giving you a place to stash marketing-only layouts, tests, or assets. nextjs.orgYou can also colocate non-route files—utilities, styles, tests—inside any segment because only page.js
/ route.js
become public routes. nextjs.org
5 · Pages Router vs App Router Quick-Look
Pages Router (pages/ ) |
App Router (app/ ) |
|
---|---|---|
Page file name | index.js per folder |
page.js |
Data hooks | getStaticProps , getServerSideProps |
Native fetch() in Server Components |
Global wrappers | _app.js , _document.js |
Hierarchical layout.js files |
Streaming / RSC | Limited | Built-in (React Server Components) |
Future direction | Maintenance mode | Active development |
Migrating is incremental—pages/
and app/
can coexist while you move routes. nextjs.org
6 · Route Handlers (API in the App Router)
The App Router replaces pages/api/*
with route.js
(or .ts
). Export the HTTP verbs you need:
// app/api/hello/route.js
export async function GET() {
return Response.json({ hello: 'world' });
}
Handlers run in the edge runtime by default and share the same path conventions as pages. nextjs.org
7 · Advanced Patterns
-
Parallel Routes & Intercepting—render multiple segments side-by-side or hijack a sibling route (
(modal)/@modal
). nextjs.org -
Middleware (
middleware.ts
)—regex-based guard runs before the route file system match. -
Internationalized routes—combine
middleware.ts
withheaders()
to rewrite/es/blog
.
8 · Common Pitfalls & Tips
-
Missing
layout.js
at the root → your nested layouts may not render; create one early. -
Dynamic mismatch—
[id]
folder but forgetting to readparams.id
in the page component. -
Client-only code inside Server Components—add
"use client"
at the top of the file or move logic to a nestedClient.tsx
. -
Large asset imports—remember only what
page.js
returns is shipped; colocated helper files aren’t.
9 · When to Reach for the Pages Router
-
You’re maintaining a legacy Next.js 12 project.
-
You need quick static pages without learning new conventions.
Otherwise, the App Router’s streaming, layouts, and colocated route handlers make it the forward-compatible choice.
10 · Key Takeaways
-
Folder names become URL segments;
page.js
is the render target. -
Dynamic segments (
[id]
,[...slug]
) make paramized paths trivial. -
Layouts, loading, and error files give instant UX scaffolding.
-
Route Handlers turn any segment into an API endpoint.
-
The App Router is the future; migrate incrementally from
pages/
.
With these conventions, you can scaffold an entire production app without ever touching a router config. Drop a file, write your component, and ship 🚀
Frequently Asked Questions (FAQs)
Topic — File-Based Routing in Next.js 15
# | Question | Answer |
---|---|---|
1 | What is file-based routing in Next.js? | Your folder & file structure inside app/ (or the legacy pages/ ) automatically maps to URL paths—no manual router config needed. |
2 | What’s the difference between app/ and pages/ ? |
app/ (App Router) is the modern, RSC-powered system with page.js , nested layout.js , streaming, and Route Handlers. pages/ (Pages Router) is the older pattern that relies on getStaticProps /getServerSideProps . Both can coexist while you migrate. |
3 | How do I create a dynamic route like /post/123 ? |
Wrap the segment name in brackets: app/post/[id]/page.js . Inside the component, read params.id . |
4 | Can I capture an arbitrary slug depth (e.g., /docs/guide/setup )? |
Yes—use a catch-all segment: app/docs/[...slug]/page.js , which provides params.slug as an array of path parts. |
5 | What if I need a folder for tests or styles but don’t want it in the URL? | Use a route group: (marketing)/ or (tests)/ . Parentheses exclude the segment from the final path while keeping files colocated. |
6 | How do I share a header or sidebar across many pages? | Add a layout.js file in the highest common folder. Layouts nest automatically, so children inherit the wrapper. |
7 | Where do API endpoints live in the App Router? | In any segment, create route.js (or route.ts ). Export HTTP functions (GET , POST , etc.). The file path sets the endpoint URL just like a page.js . |
8 | Is React Router still needed inside Next.js? | No. Next.js handles all client-side navigation with the built-in <Link> component and router hooks (useRouter() ). |
9 | How do I add loading states per route? | Drop a loading.js file next to page.js or layout.js . It renders instantly while the parent Server Component streams data. |
10 | What’s the best way to handle 404 pages? | In the root of app/ , add not-found.js . Next.js shows this component whenever a route doesn’t match. |
11 | Can I keep some routes static and others server-rendered? | Absolutely—export export const revalidate = 0 for static (SSG), set a number for ISR, or omit it for full SSR. Each page.js controls its own caching. |
12 | Do I have to migrate my old Pages Router project? | Not immediately. Pages Router is still supported, but new features (Server Components, parallel routes, Route Handlers) live in App Router, so most teams migrate incrementally for future-proofing. |