跪拜 Guibai
← All articles
React.js · Frontend Engineering · Next.js

Next.js App Router Routing Is Just Files in the Right Folders

By 烬羽 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Convention-based routing eliminates an entire category of boilerplate—no route tables, no separate API server, no manual wiring between layouts and pages. But the trade-off is that the directory structure is the source of truth, so dynamic segments like `/post/:id` require a different mechanism, and the server/client boundary demands careful placement of data-fetching logic to avoid empty first paints.

Summary

A Next.js project with zero route configuration still serves pages at `/`, `/about`, `/dashboard`, and `/api/todos`. The secret is that `app/` directory structure maps directly to URLs: `page.tsx` becomes a page, `layout.tsx` wraps child routes in a shared shell, and `route.ts` under `api/` exposes HTTP endpoints. All three roles are determined by filename and location, not by a central router declaration.

The `'use client'` directive marks a component for hydration—it still renders on the server first, then ships JavaScript to the browser to activate interactivity. This means a `useEffect` data fetch won't populate the initial HTML; the first paint shows an empty state until hydration completes. Three common beginner mistakes surface in the demo code: a POST handler that never updates local state, a delete button with no click handler, and leftover `console.log` calls.

Takeaways
Folders under `app/` become URL segments; `app/about/page.tsx` automatically serves `/about`.
Only files named `page.tsx` with a default export become accessible routes—other `.tsx` files are just importable modules.
`layout.tsx` wraps its directory and all subdirectories; layouts nest, so a root layout and a dashboard layout combine at `/dashboard/settings`.
`route.ts` under `app/api/` turns a folder into an API endpoint; exported function names (`GET`, `POST`) map to HTTP methods.
Components in `app/` are Server Components by default; adding `'use client'` at the top makes them Client Components that can use hooks and event handlers.
`'use client'` components still render on the server first—hydration sends JavaScript afterward to attach interactivity, so `useEffect` data fetches leave the initial HTML empty.
Three common bugs in the demo: a POST that never updates local state, a delete button with no `onClick`, and leftover `console.log` statements.
Conclusions

Convention-based routing shifts the developer's mental model from "configuring a router" to "organizing a filesystem," which makes project structure immediately legible but also locks URL design to directory layout.

The `'use client'` boundary is widely misunderstood as a browser-only marker; in practice it creates a dual-render lifecycle where the server produces static HTML and the browser later hydrates it, making initial data-fetching strategy critical.

Next.js blurs the frontend-backend line by letting `route.ts` files live in the same project tree as pages, which removes CORS and deployment overhead but also tempts developers to put business logic directly in route handlers.

Concepts & terms
Convention-based routing
A routing approach where URL paths are derived from the file-system directory structure rather than from an explicit route table. In Next.js App Router, `app/dashboard/settings/page.tsx` automatically serves `/dashboard/settings`.
Server Component
A React component that renders only on the server. It cannot use browser-only APIs like `useState`, `useEffect`, or event handlers, but it can directly access databases and filesystems, and its output is pure HTML sent to the client.
Client Component
A React component marked with `'use client'` at the top of the file. It renders on the server for the initial HTML, then ships a JavaScript bundle to the browser where hydration attaches interactivity (state, effects, event handlers).
Hydration
The process where the browser receives server-rendered static HTML, downloads the associated JavaScript, and React attaches event handlers and state to that existing DOM—making a static page interactive without re-rendering from scratch.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗