File-system routing
See how Next.js turns folders into URLs: each folder is a segment, page.tsx makes a route public, folders nest, and other files in app never become routes.
- 01Map folders to URLsTell which address a page.tsx makes from the folders it sits in, at any depth.
- 02Say when a route is publicExplain why a folder without page.tsx answers 404, and which file names make a page.
- 03Keep other files beside your pagesPut components and data next to the page that uses them, knowing they never get an address.
Folders become addresses
A route is an address in your app, like /teas, and the page it shows. Most tools ask you to list your routes in code. Next.js doesn't: its App Router, the router this course teaches, reads the folders inside app, and the folders are the list. That's called file-system routing. If you built the notes app in Your first Next.js app, you already used it: app/new/page.tsx was the page for /new. This lesson gives you the rules behind that.
Here is the tea shop with three pages. Like every example in this lesson, it's a real Next.js 16.4.3 project, built with next build and run with next start, and what it sent back was recorded. Click through its files, then its pages.
app/teas/page.tsxexport default function TeasPage() { return ( <main> <h1>Our teas</h1> <ul> <li>Green tea</li> <li>Mint tea</li> </ul> </main> );}Fresh tea, sent to your door.
The page as the browser shows it when its HTML arrives, drawn with plain styles. Its JavaScript doesn't run here.
app/teas/page.tsx exports its component with export default on line 1, and line 4 is its heading, Our teas. Nothing in the file says /teas: its place does. The file sits in a folder named teas, inside app, so it's the page for /teas. In the same way, app/page.tsx is / and app/about/page.tsx is /about. app/layout.tsx is the root layout: it goes around every page, and its links on line 10 lead to all three.
Open the Terminal tab. After building, next build prints the routes it found: ○ /, ○ /_not-found, ○ /about and ○ /teas. You never wrote that list. The build made it from the folders, and added /_not-found, the page for addresses that don't exist. The ○ in front of each one means prerendered as static content, as the legend under the table says: every page in this lesson is. In the Browser tab, click Teas and About to switch between the recorded pages.
app folder. Each page file becomes the address of the folders it sits in. layout.tsx has no address: it goes around every page.A postal address narrows down step by step: the street, then the house on it, then the flat inside. A visitor can only knock where there's a front door. A hallway between flats has no door of its own, and the boxes stored inside a flat have no address of their own.
- In real life: Each part of a postal address: the street, then the house, then the flat
- In Next.js: Each folder: one part of the URL, in order
- In real life: A front door with a bell, where visitors can knock
- In Next.js: A
page.tsx, which makes the address a page - In real life: A hallway with no door of its own
- In Next.js: A folder without
page.tsx: its address answers 404 - In real life: Boxes stored inside a flat
- In Next.js: Other files beside
page.tsx, which get no address of their own
In the App Router, the folders in app are your routes. Each folder is one part of the address, and a page.tsx in a folder makes that address a page that visitors can open. Ordinary files beside it, like a component or some data, get no route of their own: page and route are the two files that make a route public.
One folder for each part of the address
The part of a URL after the site's name is its path: in localhost:3000/teas/green, the path is /teas/green. The / characters split a path into parts called segments: here, teas and green. Next.js matches each segment with one folder, in order:
/teas/green in parts: the root segment /, then teas, then green. Each part is one folder, and the page.tsx in the last folder is the page.- The root segment is
appitself. It stands for/, and its name never shows in the address. That's whyapp/page.tsxis the page for/, not/app. - Every folder inside
appis one more segment, with the folder's name as the text of the address:app/teasis/teas. - A folder inside that one adds the next segment:
app/teas/greenis/teas/green.
Each row is one address from this lesson's recordings: its segments, and the folder its page sits in.
| Address | Its segments | The folder of its page |
|---|---|---|
/ | None: the root segment | app |
/teas | teas | app/teas |
/teas/green | teas, then green | app/teas/green |
/account/orders | account, then orders | app/account/orders |
Because a folder's name is the text of the address, name folders the way you want the address to read: short, lowercase words, with hyphens between them, like gift-boxes for /gift-boxes.
Folders inside folders
A route made of several segments is a nested route. The shop wants a page for each tea, so app/teas gets a folder for each: green and mint, each with its own page.tsx. The list at /teas now links to them.
app/teas/green/page.tsxexport default function GreenTeaPage() { return ( <main> <h1>Green tea</h1> <p>Light and fresh. $4 a box.</p> </main> );}The page as the browser shows it when its HTML arrives, drawn with plain styles. Its JavaScript doesn't run here.
app/teas/green/page.tsx is an ordinary page: a heading on line 4 and a line about the tea on line 5. Its folders, teas then green, make its address /teas/green. In app/teas/page.tsx, lines 9 and 12 link to /teas/green and /teas/mint.
The Terminal lists two new routes, ○ /teas/green and ○ /teas/mint, under ○ /teas. In the Browser, click Green tea. The page shows the layout's links, then Green tea and Light and fresh. $4 a box., and nothing from the /teas page. A nested route doesn't show its parent page; each address shows one page. What pages share goes in a layout, and folders can have layouts of their own, which the next lesson shows.
One folder for each tea works for two teas. For two hundred, you write one folder whose name is a placeholder, and Next.js fills it from the address. That's a dynamic route, a few lessons on, in Dynamic routes.
page.tsx makes a route public
A folder gives a route its place, but not a page. Only a page file makes the route public: an address that visitors can open. The shop's account area shows the difference. It has app/account/orders/page.tsx, so /account/orders is a page. The folder above it, app/account, holds only that folder. Pick a version, then look at what /account answered.
app/account folderNext.jsapp/account/orders/page.tsxexport default function OrdersPage() { return ( <main> <h1>Your orders</h1> <p>No orders yet.</p> </main> );}The page as the browser shows it when its HTML arrives, drawn with plain styles. Its JavaScript doesn't run here.
The folder account holds only another folder. /account/orders is a page, but /account has no page.tsx, so it answers 404, with the page Next.js made for addresses that don't exist.
In the first version, /account answered with a page that says 404 and This page could not be found. Open its Network tab: the status is 404, the title is 404: This page could not be found., and the page is the one Next.js made as /_not-found. The route table has ○ /account/orders but no /account. In the second version, app/account/page.tsx adds ○ /account, and the same request answers 200 with Your account.
next build lists every route. A request for /account/orders finds its page. /account isn't in the list, because app/account has no page file, so Next.js answers with the 404 page.So next build reads the folders and builds a tree of routes from them. In this shop, every route is a fixed address, so the tree is the list in the Terminal: a request for a path in it gets its page, and any other path gets the 404 page. A route can also be a pattern, with a folder name like [slug] that matches addresses the build never listed; Dynamic routes shows those.
Which names count as a page file? Each button below is the same About page, saved under a different name. Before you click, guess which ones make /about.
app/about/page.tsxexport default function AboutPage() { return ( <main> <h1>About us</h1> <p>We sell tea from one small shop.</p> </main> );}$ next build▲ Next.js 16.4.3 (Turbopack)- Cache Components enabled- Partial Prefetching enabled Creating an optimized production build ...✓ Compiled successfully Running TypeScript ... Finished TypeScript ... Collecting page data ...✓ Generating static pages (5/5) Finalizing page optimization ... Route (app)┌ ○ /├ ○ /_not-found├ ○ /about└ ○ /teas ○ (Static) prerendered as static contentA folder named about with a page.tsx in it: the build lists ○ /about, and /about answers 200 with the page.
about/page.tsx and about/page.js make a page: the App Router accepts page.js, page.jsx and page.tsx. about/index.tsx and about.tsx don't, and /about answers 404. Those two names come from the Pages Router, Next.js's older router, which reads a pages folder: there, every file is a page, pages/about.tsx is /about, and pages/index.tsx is /. It's still supported, and you'll meet it in older projects. In the App Router, only page files make pages.
A route.ts file makes a route public too, but it answers with data, like JSON, instead of a page. It's called a Route Handler, and Route Handlers, in the Fetching and mutating data stage, teaches it. A folder holds a page file or a route.ts, not both.
Files that never become routes
Since only page files make addresses here, every other file in app has no address. You can keep a page's own parts right next to it, which is called colocation. Here, the teas page takes its list from data.ts and draws each tea with tea-card.tsx, both in app/teas.
app/teas/page.tsximport TeaCard from "./tea-card";import { teas } from "./data"; export default function TeasPage() { return ( <main> <h1>Our teas</h1> <ul> {teas.map((tea) => ( <TeaCard key={tea.slug} name={tea.name} price={tea.price} /> ))} </ul> </main> );}- Green tea: $4
- Mint tea: $3
The page as the browser shows it when its HTML arrives, drawn with plain styles. Its JavaScript doesn't run here.
Lines 1 and 2 of app/teas/page.tsx import the two files beside it. Line 10 draws a TeaCard for each tea in teas. The /teas page shows Green tea: $4 and Mint tea: $3, so both files did their job.
Now pick /teas/tea-card and /teas/data in the Browser tab. The recorder asked for both, and both answered 404. The route table still has one route for the folder, ○ /teas. A component or a data file beside a page is part of that page, and has no address of its own.
A file without an address can still reach the browser in other ways. What a page renders is in its HTML: both teas' names and prices from data.ts are right there in the Network tab. And the code of a Client Component, with everything its file imports, is sent to the browser too. So never keep a secret, like a password or a key, in a file just because it has no address. The Server-only code and environment variables lesson shows where secrets belong.
app/teas, one address. page.tsx is the page for /teas, and it uses the other two files. tea-card.tsx and data.ts have no address: /teas/tea-card and /teas/data answer 404.Other files in app never become routes either. layout.tsx goes around pages, and other special files, like loading.tsx for a loading screen, each do one job for a route, as the next lessons show. Two folder names change the rules on purpose: a folder whose name starts with _, like _components, is left out of routing with everything in it, and a folder in brackets, like (shop), groups routes without adding a segment. Route groups and private folders, later in this stage, covers both.
Planning the tea shop's folders
When you plan an app, start from the addresses you want, then make a folder for each segment and a page file where the address should open. Each row is one address the recordings in this lesson served, and the file that made it.
| Address | File | What it shows |
|---|---|---|
/ | app/page.tsx | The home page. |
/teas | app/teas/page.tsx | The list of teas. |
/teas/green | app/teas/green/page.tsx | One tea's page. |
/about | app/about/page.tsx | About the shop. |
/about/team | app/about/team/page.tsx | The people who pack the boxes. |
/account | app/account/page.tsx | The visitor's account. |
/account/orders | app/account/orders/page.tsx | The visitor's orders. |
Notice /account and /account/orders: they're two pages, so they need two page files, one in each folder. Now sort these files: which ones make a page?
app/page.tsxapp/teas/green/page.tsxapp/about/page.jsapp/about/index.tsxapp/about.tsxapp/teas/tea-card.tsxapp/teas/data.tsapp/layout.tsx
Sort each file of the tea shop: does it make a page, or is it never a page?
Common mix-ups
- "Every file in
appis a page." No. Only page files are./teas/tea-cardand/teas/dataanswered404. - "
app/about.tsxmakes/about." No. Only folders make segments: the recorded/aboutanswered404. - "
index.tsxis a folder's page." No. That's the Pages Router. The App Router looks forpage.tsx,page.jsxorpage.js. - "A folder is enough to make its address work." No. Without a page file,
/accountanswered404, though/account/ordersworked. - "A nested page shows its parent page too." No.
/teas/greenshowed only its own page, inside the layout. Shared parts go in layouts. - "You list the routes somewhere." No.
next buildreads the folders and prints the list itself.
Practice exercises
These exercises are about Next.js projects, which can't run inside this page. Answer first, then use the hints.
These are the shop's files. Which address does app/teas/green/page.tsx make?
app/
about/
page.tsx
teas/
green/
page.tsx
mint/
page.tsx
page.tsx
layout.tsx
page.tsx/teas/green. app is the root, /; teas and green are the next two segments. The recorded build lists ○ /teas/green.
The shop wants this page at /about/team. Where does the file go?
export default function TeamPage() {
return (
<main>
<h1>Our team</h1>
<p>Asha and Ravi pack every box.</p>
</main>
);
}
app/about/team/page.tsx. The recorded build of the shop with this file lists ○ /about/team, and /about/team shows Our team.
With these files, one of /account and /account/orders answers 404. Which one?
app/
about/
page.tsx
account/
orders/
page.tsx
teas/
page.tsx
layout.tsx
page.tsx/account. The folder account has no page file, so its route isn't public. /account/orders works, and /account answered 404 in the playground's first version.
A teammate saved this About page as app/about/index.tsx, and /about answers 404. What should the file be named?
export default function AboutPage() {
return (
<main>
<h1>About us</h1>
<p>We sell tea from one small shop.</p>
</main>
);
}
page.tsx, so the file is app/about/page.tsx. The code stays the same: only the name was wrong. index.tsx is a Pages Router name, and the App Router ignores it.
A visitor types /teas/tea-card. What does the shop answer?
app/
teas/
data.ts
page.tsx
tea-card.tsx404. Only page.tsx makes an address in this folder, /teas. The recorder asked for /teas/tea-card and got the 404 page, with the status 404.
With this file as app/about/page.js, next build stops with The default export is not a React Component in "/about/page". What's missing?
export function AboutPage() {
return (
<main>
<h1>About us</h1>
<p>We sell tea from one small shop.</p>
</main>
);
}
export default function AboutPage() {
return (
<main>
<h1>About us</h1>
<p>We sell tea from one small shop.</p>
</main>
);
}
export default. A page file must export its component as the default export. The recorded build stopped with: The default export is not a React Component in "/about/page".
Check your understanding
For each question, walk the folders from app, and ask whether the last one has a page file.
Question 1 of 7Which address does
app/teas/mint/page.tsxmake?Choose an answer to see the explanation.
Question 2 of 7This shop has no
app/account/page.tsx. What does/accountanswer?Read the code, then predictTextapp/ about/ page.tsx account/ orders/ page.tsx teas/ page.tsx layout.tsx page.tsxChoose an answer to see the explanation.
Question 3 of 7Which of these files makes
/abouta page?Choose an answer to see the explanation.
Question 4 of 7Where does the list of routes that
next buildprints come from?Choose an answer to see the explanation.
Question 5 of 7What does the recorded
/teas/greenshow?Choose an answer to see the explanation.
Question 6 of 7
app/teas/tea-card.tsxsits next toapp/teas/page.tsx. What does/teas/tea-cardanswer?Choose an answer to see the explanation.
Question 7 of 7Which folders does Next.js follow for
/account/orders?Choose an answer to see the explanation.
Key takeaways
- The App Router builds its routes from the folders in
app.next buildprints the list; you never write it. - Each folder is one segment of the address.
appis the root segment,/, soapp/teas/greenis/teas/green. - A
page.tsx(orpage.jsx, orpage.js) makes a route public. A folder without one answers404, even when the folders inside it have pages. - Each address shows one page, inside the layout. A nested page doesn't show its parent page.
- Every other file in
app, like a component or data beside a page, never gets an address.index.tsxandabout.tsxare Pages Router names, not App Router pages.
Remember the one-liner.
Folders make the address, and page.tsx opens the door.
Coming next: Layouts and pages. It shows the root layout in full, layouts inside folders that wrap only their own pages, and the props each one gets.