Course outline · 0% complete

0/29 lessons0%

Course overview →

Anatomy of a Next.js project

lesson 2-1 · ~10 min · 4/29

Before opening a project, it is worth restating where the previous lesson, Rendering on the server: the big idea, left off.

Hydration attaches React's event listeners so the already-rendered HTML becomes interactive. The server ships finished HTML first, then React hydrates it in the browser: it walks the existing DOM, wires up handlers and state, and takes over without rebuilding anything. That is what turns a static photograph of your app into the live app.

Keep that two-act structure in mind. The folder layout you are about to meet exists to make both acts easy to write.

Your first tour

Before frameworks, starting a React project that also had a server meant hours of setup: a bundler, a dev server, routing, and two configs that drift apart. Every team did it differently, so joining a new codebase meant relearning the layout. Next.js removes both costs with one scaffold command and one folder convention that every Next.js project on earth shares. Learn this layout once and you can navigate any Next.js repo at work.

A Next.js app is scaffolded with one command, just like the Express generators you met in Backend with Node.js:

npx create-next-app@latest my-app

The result is a normal Node project (there is a package.json, and npm run dev starts it) with one special folder at its heart:

my-app/
├── app/
│   ├── layout.js      ← wraps every page (html, body)
│   ├── page.js        ← the / homepage
│   └── globals.css
├── public/            ← static files served as-is
├── next.config.js     ← framework settings
└── package.json

Everything routing-related lives in app/. That folder is your sitemap.

A recorded session: scaffold to running server

Here is the sequence a developer goes through on day one of any Next.js project, with the output each command printed.

Step 1. Scaffolding a new project. The wizard asks a few setup questions, about TypeScript and Tailwind for example, and the defaults are fine while learning.

$ npx create-next-app@latest my-app
Creating a new Next.js app in ./my-app
Installing dependencies...
Success! Created my-app

Step 2. Stepping inside and listing what was generated. The app/ folder is the one that matters, because that is where routing lives.

$ cd my-app
$ ls
app  next.config.js  node_modules  package.json  public

Step 3. Starting the development server, then opening the printed URL in a browser. Edits to files under app/ hot-reload instantly, so the browser updates without a manual refresh.

$ npm run dev
▲ Next.js
- Local: http://localhost:3000
✓ Ready

Three commands and there is a working, server-rendering React app. Compare that with the multi-day bundler setup this used to require.

The special file names

Inside app/, Next.js only treats a handful of file names as special. Everything else (components, helpers) is just code you import.

FileJob
page.jsThe UI for a URL. A folder without one is not a page
layout.jsShared shell wrapped around pages below it
loading.jsInstant fallback while a page loads (Unit 4)
error.jsShown when a page throws (Unit 4)
not-found.jsShown for missing content (Unit 5)
route.jsAn API endpoint instead of a page (Unit 6)

The first two are worth committing to memory now. The rest each get their own lesson later.

A folder without page.js is not a route

Suppose you create app/pricing/ and put a single file in it called helpers.js. The URL /pricing returns a 404.

A folder only becomes a working page when it contains a page.js file. That file is the signal to the router: render this component at this URL. Any other file in the folder, helpers.js, utils.js, a component file, is ignored by the router and treated as ordinary importable code. Since app/pricing/ has no page.js, there is no UI to render, so Next.js responds with a 404.

This is a useful property, not an annoyance. It means you can colocate helpers, components, and tests right next to the page that uses them without accidentally creating public URLs.