~/TechPurAI
~/tutorials/nextjs-from-scratch/pages-and-file-based-routing
beginner·part 2 of 22·3 min read

Pages and file-based routing

Updated Aug 31, 2026JavaScript · Next.js

There's no separate routing configuration file to maintain in the App Router — the folder structure inside app/ is the routing table. This part adds the blog's first real route, and covers exactly which folders the router notices and which it ignores.

Folders map directly to URL segments

text
app/
    page.tsx              →  /
    about/
        page.tsx           →  /about
    posts/
        page.tsx           →  /posts
tsx
// app/posts/page.tsx
export default function PostsPage() {
  return <h1>All posts</h1>;
}

Create app/posts/page.tsx with the component above, and /posts works immediately — no route registration, no import into a central router file. The folder name becomes the URL segment; nesting folders nests URL segments the same way.

Not every folder becomes a route

text
app/
    posts/
        page.tsx           →  /posts   (has a page.tsx — routable)
    components/
        PostCard.tsx        →  nothing (no page.tsx — not a route)

A folder inside app/ only becomes a visitable route if it directly contains a page.tsx. app/components/PostCard.tsx is a completely ordinary React component file, not a route — the presence of page.tsx specifically is what the router actually checks for, not just "is this a folder inside app/." This is what lets components, utilities, and routes live side by side in the same directory tree without colliding.

Linking between pages

tsx
// app/page.tsx
import Link from "next/link";

export default function Home() {
  return (
    <div>
      <h1>devnotes</h1>
      <Link href="/posts">Read the posts</Link>
    </div>
  );
}

A plain <a href="/posts"> would work too, technically — it would just trigger a full page reload, throwing away everything Next.js does to keep navigation fast. next/link's Link component is the one used throughout this series for any in-app navigation; part 12 covers exactly what it does beyond just rendering an anchor tag.

Common mistake

Naming a route file Page.tsx (capital P) instead of page.tsx. On a case-sensitive filesystem — the default on Linux, and what most production hosting runs — that file is invisible to the router entirely, and the route silently 404s.

FAQ

How does a route with a dynamic segment, like a specific post's URL, get created? A folder named in square brackets — app/posts/[slug]/page.tsx — matches any value in that URL position (/posts/hello-world, /posts/anything) and passes it to the page as a params prop. This series adds that once individual post pages exist, a few parts ahead.

Can I group routes into folders for organization without affecting the URL? Yes — a folder name wrapped in parentheses, like (marketing), is a route group: it organizes files in the filesystem (and can hold its own layout) without adding a segment to the actual URL. app/(marketing)/about/page.tsx still serves /about, not /marketing/about.

What if I want a folder's name in the URL but the folder has no page.tsx of its own? That's normal and expected — a folder like app/posts/ can exist purely to hold nested routes (app/posts/[slug]/page.tsx) without a page.tsx directly inside it, meaning /posts itself 404s while /posts/hello-world works. Adding a page.tsx directly in app/posts/ is what makes /posts itself a valid route, as this part does.

Next: page.tsx files render on the server by default — what that actually means, and when a component needs to opt out of it.

VK

Vijay Kumar

Founder of TechPurAI — writing hands-on tutorials and honest tool breakdowns.

LinkedIn ↗
← previous1. Creating a Next.js project: the App Router folder structurenext →3. Server Components and Client Components: the default and the escape hatch