File-based Routing
In React Router (ReactNotes), YOU write the routes: <Route path='/blog' element={<Blog />} />. In Next.js, the FOLDER STRUCTURE under app/ is the route table — there's no routes file at all.
Explain it like I'm 5
Think of app/as a filing cabinet. Whatever folder path you create, that's the URL. A folder named blog containing a page.tsx becomes the URL /blog. No import, no registration, nothing to keep in sync.
1. The rule: page.tsx makes a route
Only a file literally named page.tsx (or page.js) inside a folder is publicly routable. Any other file in that folder — components, helpers, styles — is just a regular module, invisible to the router.
app/
page.tsx -> "/"
about/
page.tsx -> "/about"
blog/
page.tsx -> "/blog"
[slug]/
page.tsx -> "/blog/anything-here" (dynamic segment)
dashboard/
page.tsx -> "/dashboard"
settings/
page.tsx -> "/dashboard/settings" (nested route)2. Special filenames Next.js reserves inside a route folder
These aren't routes themselves — they're conventions the router looks for automatically at each level of the folder tree.
layout.tsx shared UI that wraps this segment and everything below it
loading.tsx shown instantly while this segment's page.tsx is loading
error.tsx catches errors thrown by this segment (must be a Client Component)
not-found.tsx shown when notFound() is called or no route matches
route.ts an API endpoint instead of a page (can't co-exist with page.tsx)3. Dynamic segments — [slug]
Square brackets in a folder name capture part of the URL as a parameter. This one file matches /blog/hello, /blog/anything — every value goes through the same component.
// app/blog/[slug]/page.tsx
export default async function BlogPostPage({
params,
}: {
params: Promise<{ slug: string }>
}) {
// params is a Promise in this Next.js version — it must be awaited
const { slug } = await params
return <h1>Post: {slug}</h1>
}Live result
See it live: /blog lists posts, and /blog/using-app-router is one dynamic match.
4. Route groups & layouts (not demoed live here)
Wrapping a folder name in parentheses, e.g. (marketing), groups routes for organization or a shared layout without adding a URL segment. Every folder can also have its own layout.tsx that nests inside its parent's layout — this app's sidebar comes from the ROOT app/layout.tsx, which wraps every single page.
app/
(marketing)/
layout.tsx <- shared layout, but "(marketing)" adds NOTHING to the URL
page.tsx -> "/"
pricing/
page.tsx -> "/pricing"