Learn how folders and page.js files in the Next.js app folder become URLs, build the first Book Nook pages, and see which files are and are not routes.

Bishal Biswas
Self Learner
What you will learn
Every website is a collection of addresses: /, /books, /about, /cart. Each address is called a route. In many tools you write a list of routes in code. In Next.js you do not. You make folders and files, and Next.js turns them into routes for you. This is called file-based routing.
In this lesson you will:
- learn the two simple rules that turn folders into URLs
- add the first real pages to Book Nook:
/books,/aboutand/cart - nest folders to make deeper URLs like
/books/bestsellers - see which files become routes and which stay private
- get a first look at special folder names you will learn later
You need the Book Nook project from Creating Your First Next.js App, with the dev server running (npm run dev).
The two rules
Think of the app folder as a building, and the URL as directions to a room. Each folder is a door you walk through. A page.js file is the sign on the room that says “open to visitors”.
- Folders make URL segments. A segment is one piece of a URL between slashes. In
/books/bestsellers, the segments arebooksandbestsellers. The folderapp/booksmakes thebookssegment. - A
page.jsfile makes the route public. A folder without apage.jsis just a corridor. You can walk through it, but there is nothing to see there.
Here is how it looks:
app/
├── page.js → /
├── about/
│ └── page.js → /about
├── books/
│ ├── page.js → /books
│ └── bestsellers/
│ └── page.js → /books/bestsellers
└── cart/
└── page.js → /cart
The app folder itself is the root, /. That is why app/page.js is your home page. There is no index.js in the App Router: the file is always called page.js.
Step 1: add an About page
Create a new folder app/about, and inside it a file called page.js:
// app/about/page.js
export default function AboutPage() {
return (
<main className="mx-auto max-w-2xl p-8">
<h1 className="text-3xl font-bold">About Book Nook</h1>
<p className="mt-4">
Book Nook is a small, independent bookshop. We pick every book by hand
and ship it with care.
</p>
</main>
);
}
Save, and open http://localhost:3000/about. Your page is there. You did not register the route anywhere, import anything, or restart the server. The folder and file were enough.
The terminal confirms it:
○ Compiling /about ...
GET /about 200 in 1621ms (next.js: 1455ms, application-code: 166ms)
A few things to notice:
- The file must
export defaulta React component. That is how Next.js finds the page. - The component name does not matter.
AboutPage,PageorAboutall work. Pick a name that helps you read the code. - The folder name decides the URL. Rename
abouttoabout-us, and the page moves to/about-us.
Step 2: add the books and cart pages
Make two more folders, each with its own page.js:
// app/books/page.js
export default function BooksPage() {
return (
<main className="mx-auto max-w-2xl p-8">
<h1 className="text-3xl font-bold">All books</h1>
<ul className="mt-4 list-disc pl-6">
<li>The Hobbit</li>
<li>Pride and Prejudice</li>
<li>Dune</li>
<li>The Little Prince</li>
</ul>
</main>
);
}
// app/cart/page.js
export default function CartPage() {
return (
<main className="mx-auto max-w-2xl p-8">
<h1 className="text-3xl font-bold">Your cart</h1>
<p className="mt-4">Your cart is empty.</p>
</main>
);
}
Visit /books and /cart to see them. For now the list of books is typed by hand. In Dynamic Routes and params you will load it from a data file instead.
Step 3: nest folders for deeper URLs
To make /books/bestsellers, put a bestsellers folder inside books:
// app/books/bestsellers/page.js
export default function BestsellersPage() {
return (
<main className="mx-auto max-w-2xl p-8">
<h1 className="text-3xl font-bold">Bestsellers</h1>
<ol className="mt-4 list-decimal pl-6">
<li>Dune</li>
<li>The Hobbit</li>
</ol>
</main>
);
}
Each level of folders adds one segment to the URL. You can nest as deep as you like:
| File | URL |
|---|---|
app/page.js |
/ |
app/books/page.js |
/books |
app/books/bestsellers/page.js |
/books/bestsellers |
app/books/bestsellers/this-week/page.js |
/books/bestsellers/this-week |
/books and /books/bestsellers are separate pages. Each one has its own page.js, and neither one needs the other to exist.
Folders without a page.js
What happens if a folder has no page.js? Let us try. Create an empty folder app/staff and visit /staff. You get the built-in 404 page:
404
This page could not be found.
404 is the web’s code for “not found”. The folder exists, but because it has no page.js, it is not a public route. The same happens for any address you never created, like /unicorns. You will design your own friendly 404 page in Not Found Pages and Redirects.
A folder without a page can still be useful. It can hold other folders. For example, you could have app/account/orders/page.js (/account/orders) without any app/account/page.js. Then /account/orders works, and /account shows the 404 page.
Other files in app are safe
Only special file names, like page.js, create routes. Any other file inside app is ignored by the router. That means you can keep helper files right next to the page that uses them:
app/books/
├── page.js → /books (a route)
├── book-list.js not a route, just a component file
└── prices.js not a route, just a helper file
Visiting /books/book-list shows the 404 page, not your component. Keeping files close to where they are used is called colocation.
// app/books/prices.js
export function formatPrice(price) {
return `$${price.toFixed(2)}`;
}
// app/books/page.js
import { formatPrice } from './prices';
export default function BooksPage() {
return <p>Paperbacks from {formatPrice(8.75)}</p>;
}
In Book Nook, most shared code will live outside app, in components/ and lib/ folders, as you saw in Understanding the Project Files. Both styles are fine. Pick one and be consistent.
page.js and route.js
There is one more file that makes a route public: route.js. Instead of a web page, it returns raw data, like JSON for an API. Book Nook will have one at /api/books:
app/api/books/route.js → /api/books (returns JSON, not a page)
A folder can have a page.js or a route.js, but not both, because one URL cannot be a page and an API at the same time. You will build route handlers in Building APIs with Route Handlers.
A peek at special folder names
Some folder names have extra powers. You do not need them yet, but it helps to recognise them:
| Folder name | Example | What it does | Lesson |
|---|---|---|---|
[name] |
app/books/[id] |
A dynamic segment: one page for many URLs, like /books/dune and /books/the-hobbit. |
Dynamic Routes and params |
(name) |
app/(shop)/cart |
A route group: organises folders without adding to the URL. | Route Groups and Private Folders |
_name |
app/_components |
A private folder: never a route, even with a page.js inside. |
Route Groups and Private Folders |
@name |
app/@modal |
A slot for showing two pages side by side. | Parallel Routes and Intercepting Routes |
How Next.js decides what to show
When someone visits /books/bestsellers, Next.js walks the app folder like this:
- Start at
app. - Look for a folder called
books. Found it, go inside. - Look for a folder called
bestsellers. Found it, go inside. - Is there a
page.jshere? Yes, so render it.
If any step fails (no such folder, or no page.js at the end), the visitor gets the 404 page. It is like following signs in a building: if a door is missing, you are lost.
There is one more step you will learn next: on the way down, Next.js also collects any layout.js files it passes. They wrap the page in shared UI like a header and footer. That is the topic of Pages and Layouts.
Good habits for folder names
The folder name is exactly what appears in the URL, so:
- Use lowercase letters:
bestsellers, notBestsellers. - Use dashes between words:
new-arrivals, notnew_arrivalsornewArrivals. Dashes are the web’s usual style and read well in links. - Keep names short and meaningful. Visitors and search engines both read URLs.
app/books/new-arrivals/page.js → /books/new-arrivals good
app/books/NewArrivals/page.js → /books/NewArrivals avoid
Common mistakes
Naming the file after the route
Coming from older tutorials, you might create app/about.js or app/about/about.js. Neither works. In the App Router the folder is named after the route and the file is always page.js:
app/about.js wrong: not a route
app/about/about.js wrong: not a route
app/about/index.js wrong: not a route
app/about/page.js right: shows at /about
Forgetting export default
If the page has no default export, you see this in the terminal and the error overlay:
⨯ Error: The default export is not a React Component in "/about/page"
Make sure the file has export default function SomeName() { ... }.
Putting the folder in the wrong place
app/bestsellers/page.js gives you /bestsellers, not /books/bestsellers. If a page appears at an unexpected address, check how deep its folder sits inside app.
Expecting a folder alone to be a page
An empty app/staff folder shows the 404 page. Add a page.js to make it public.
Quick recap
- Each folder inside
appis one URL segment. Nesting folders makes deeper URLs. - A
page.jsfile (with a default export) makes that folder a public route.app/page.jsis/. - Folders without
page.js, and any other files inapp, are not routes. You can safely colocate helpers next to pages. route.jsmakes an API route instead of a page. A folder cannot have both.- Special folder names like
[id],(group),_privateand@slotadd extra powers, covered in later lessons. - Use lowercase, dash-separated folder names, because they become your URLs.
// app/books/page.js: the /books page (folder "books" + file "page.js")
// Folder map so far:
// app/page.js -> /
// app/about/page.js -> /about
// app/books/page.js -> /books
// app/books/bestsellers/page.js -> /books/bestsellers
// app/cart/page.js -> /cart
// The page must be the default export. The function name is up to you.
export default function BooksPage() {
return (
<main className="mx-auto max-w-2xl p-8">
<h1 className="text-3xl font-bold">All books</h1>
<ul className="mt-4 list-disc pl-6">
<li>The Hobbit</li>
<li>Pride and Prejudice</li>
<li>Dune</li>
<li>The Little Prince</li>
</ul>
</main>
);
}
// --- next file: app/books/bestsellers/page.js (shows at /books/bestsellers)
// export default function BestsellersPage() {
// return <h1 className="text-3xl font-bold">Bestsellers</h1>;
// }
Was this explanation helpful?
Your feedback helps us improve the content for everyone.
Thank you for your feedback!
We appreciate you helping us improve.
What could we improve? (Optional)
Read aloud
Ready