AV
HomeAboutProjectBlog

© 2026 Ave syah Shina. All rights reserved.

  1. Home
  2. Blog
  3. 04 — Routing Foundations — The File System Is the Router

04 — Routing Foundations — The File System Is the Router

August 13, 20265 min read
Download as Markdown

The foundation everything else in the framework builds on turned out to be visible from the file explorer. The model that finally clicked: the file system is the router. Directories and files under app/ (or the legacy pages/) map directly to URL segments, so the application's entire route tree is visible at a glance in the project explorer [1][2]. There is no central route configuration file to maintain — the directory structure is the configuration.

That single decision — file-system routing — is what makes Next.js feel like "just make files and they're routes" instead of "declare routes, then wire them up."

The core vocabulary

The Next.js router has a small set of terms, and getting them straight up front saves confusion later [3]:

  • Route — a specific URL path that maps to a component, e.g. /blog/my-first-post.
  • Route segment — one part of the URL path. In /blog/my-first-post, both blog and my-first-post are segments. Each segment corresponds to one folder in the project.
  • File-system routing — the convention that the directory structure inside app/ or pages/ directly defines the routes [1][2].
  • Dynamic route — a segment that takes a parameter, written as a folder named [slug]. The bracket notation marks it as dynamic; the value is filled in at request time.
  • Index route — the route served at a directory's root, represented by a page.js (App Router) or index.js (Pages Router) inside a folder.
  • Layout — a component that wraps multiple pages, providing shared UI like headers and footers across routes.
  • Link component — next/link, used for client-side navigation between routes, which is faster than a full page load via <a>.

How files become URLs

The mapping is mechanical. Given this structure under app/:

app/
├── page.tsx → /
├── blog/
│ ├── page.tsx → /blog
│ └── [slug]/
│ └── page.tsx → /blog/:slug
└── about/
└── page.tsx → /about

Each nested folder is a route segment, and each page.tsx makes that segment publicly accessible. A folder without a page.tsx is just an organizational unit — it doesn't become a route on its own, but it can still hold a layout.tsx that wraps its children. The [slug] folder is the dynamic case: visiting /blog/hello-world and /blog/second-post both hit the same page.tsx, with hello-world or second-post available as a params prop.

file system URL app/page.tsx / app/blog/page.tsx /blog app/blog/[slug]/page.tsx /blog/hello, /blog/xyz … app/about/page.tsx /about folders = segments, page.tsx = the route becomes public

Dynamic routes — the parameterized case

Dynamic routes are where the file-system convention starts paying for itself. Instead of declaring a route with a parameter object in a config file, I just name a folder [slug] and read the parameter from the page's props:

// app/blog/[slug]/page.tsx
export default function BlogPost({ params }: { params: { slug: string } }) {
return <h1>Post: {params.slug}</h1>;
}

The bracket syntax generalizes. [slug] matches one segment; [...slug] is a catch-all that grabs the rest of the path as an array; [[...slug]] is an optional catch-all that also matches the parent path itself. These three forms cover most parameterized-route needs without ever touching a route table.

Linking between routes

Navigation between routes uses the Link component from next/link, which performs client-side navigation — it prefetches the target route and updates without a full page reload [3]. For a user clicking around a site, this is the difference between SPA-like fluidity and the flicker of traditional multi-page navigation. A plain <a> tag works but loses the prefetch and the no-reload transition.

How I use this

The file-system model changed how I think about route design. When I'm planning a feature, I sketch the URL structure first, then create the matching folders — the routes exist the moment the files do, with no wiring step. Dynamic routes handle every parameterized case I've needed, and the catch-all variants cover the rest. The mental overhead is low precisely because the file system is already a tree, and URLs are already a tree; Next.js just makes them the same tree.

References

[1] Vercel, "Routing — Pages Router," Next.js Docs, 2024. [Online]. Available: https://nextjs.org/docs/pages/building-your-application/routing

[2] Vercel, "Defining routes," Next.js Docs, 2024. [Online]. Available: https://nextjs.org/docs/14/app/building-your-application/routing/defining-routes

[3] Vercel, "Project structure and organization," Next.js Docs, 2024. [Online]. Available: https://nextjs.org/docs/app/getting-started/project-structure

[4] "Next.js 15 routing explained for beginners," YouTube, 2024. [Video]. Available: https://www.youtube.com/watch?v=qivq_vDYFGk

[5] "Next.js 15 tutorial — Dynamic routes," YouTube, 2024. [Video]. Available: https://www.youtube.com/watch?v=k9g6aVLH3p4

Knowledge check · Question 1 of 4

In Next.js App Router, how does a folder named `blog` with a `page.tsx` inside it become a route?

Comments

Leave a Comment

You must be signed in to comment

0 Comments

No comments yet. Be the first to comment!