Router Fundamentals — the mental model

[check: …]
📖 guide (.md) ← react deep dive
📖 Pair this live React playground with the companion guide (.md) — this page is the rendered ground truth. ↗ The basics — TanStack Start builds on this with SSR + server functions: frontend/tanstack-start: TanStack Start overview.

a router connects URLs to UI

Three core concepts do the work. A route tree holds the hierarchical route definitions (like a file system). history is the browser's URL state — pushState/replaceState plus popstate events. matching walks the tree for a given URL and extracts params: /users/42/posts/7 → pattern /users/:id/posts/:postId with {'{id:"42", postId:"7"}'}.

conceptroleexample
route tree hierarchical route definitions (nested like a filesystem) /users/:id/posts/:postId
history browser URL state; router listens & re-matches on change pushState({{}, '', '/users/42'}) + popstate
matching find the first route whose pattern fits the URL; extract params /users/42/posts/7PostDetail, params extracted

TanStack Router adds type-safe params/search/links, code-based OR file-based routes, search params as first-class validated state, and per-route loaders.

1 · a minimal router from scratch (edit me)

2 · Babel compiles JSX → element tree

<RouterDemo/> becomes React.createElement(RouterDemo). Typing a URL or clicking a nav button calls setCurrentPath, React re-renders, the matcher walks the route tree again, and the matched component + params update.

// (hit "compile & render" to see Babel's output)

3 · live React (the matching pipeline, proven)

Edit the URL or click a nav button. The gold-check asserts the initial /users/42/posts/7 matches PostDetail with id=42, postId=7, then clicks Home → /, then Users → /users / UserList.

live: · gold: /users/42/posts/7 → PostDetail(42,7) → Home → Users

URL → route → params → component

URLpatterncomponentparams
/ / Home {'{}'}
/users /users UserList {'{}'}
/users/42 /users/:id UserDetail {'{id:"42"}'}
/users/42/posts /users/:id/posts UserPosts {'{id:"42"}'}
/users/42/posts/7 /users/:id/posts/:postId PostDetail {'{id:"42", postId:"7"}'}
/anything/else * NotFound {'{}'}