Routing Concepts

Purpose and Scope

Routing in TanStack Router starts from a simple idea: the route tree is the application contract. A route is not only a URL pattern that renders a component; it is also the place where the application describes loader behavior, search validation, context requirements, pending and error UI, and the typed surface area used by links and navigation. This page orients developers who are learning how route definitions become a matched tree at runtime and how file-based route files participate in that contract.

Sources: docs/router/routing/routing-concepts.md

The repository documentation introduces routing concepts as a foundation for building complex and dynamic routing systems. The concepts are intentionally layered. First, a route file declares what URL it owns. Then the root route provides the always-rendered shell for the whole tree. Basic, index, dynamic, and layout routes add more expressive matching behavior. When these definitions are combined, the router can understand which branch of the application should render and which typed APIs are valid for that branch.

Sources: docs/router/routing/routing-concepts.md

Relevant Source Files

  • docs/router/routing/routing-concepts.md - Primary documentation page for route anatomy, root routes, basic routes, and the conceptual model behind TanStack Router routing.

Anatomy of a Route

Most application routes are configured with the framework-specific createFileRoute function. In React, route files import createFileRoute from @tanstack/react-router; in Solid, they import it from @tanstack/solid-router. The documentation shows a route file exporting a Route constant, where createFileRoute('/') receives the route path and returns a function that accepts options such as component. This shape is important because the exported Route is the route module’s public contract with the router and the generated route tree.

Sources: docs/router/routing/routing-concepts.md

The string passed to createFileRoute is the file route’s path. Although developers see that argument in the source file, the docs emphasize that it is automatically written and maintained by the TanStack Router Bundler Plugin or Router CLI. That means route files can be created, moved, or renamed while tooling keeps the path argument synchronized. The practical reason is type safety: TypeScript needs a stable identifier for the route file so it can connect that file to generated route types, navigation APIs, params, search schemas, and loader data.

Sources: docs/router/routing/routing-concepts.md

import { createFileRoute } from '@tanstack/react-router'
 
export const Route = createFileRoute('/about')({
  component: AboutComponent,
})
 
function AboutComponent() {
  return <div>About</div>
}

The Root Route and Application Shell

The root route is the top-most route in the entire application tree. It has no path, is always matched, and its component is always rendered. This makes it the natural place for application-wide layout, providers, and top-level error or pending boundaries. Even though it does not consume a path segment, it has access to the same kinds of route functionality as other routes, including components, loaders, and search parameter validation. In other words, the root route is not a special case that sits outside the model; it is the permanent parent of every matched branch.

Sources: docs/router/routing/routing-concepts.md

A standard root route is created with createRootRoute() and exported as the route file’s Route variable. When the application needs strongly typed shared dependencies, the docs show createRootRouteWithContext<MyRouterContext>(). A common example is passing a TanStack Query QueryClient through router context so loaders and route hooks can access the same dependency graph. This keeps cross-cutting services near router creation while preserving route-level type information for consumers that depend on that context.

Sources: docs/router/routing/routing-concepts.md

import { createRootRouteWithContext } from '@tanstack/react-router'
import type { QueryClient } from '@tanstack/react-query'
 
export interface MyRouterContext {
  queryClient: QueryClient
}
 
export const Route = createRootRouteWithContext<MyRouterContext>()

Matching Basic, Index, and Nested Routes

A basic route matches a specific path exactly. The documentation uses examples such as /about, /settings, and /settings/notifications to distinguish these routes from routes that match by position or by dynamic segment. A file declaring createFileRoute('/about') and providing an AboutComponent is therefore a direct mapping from a concrete URL pathname to rendered UI. This is the smallest useful route definition and is often the best way to understand how route options are attached to a URL.

Sources: docs/router/routing/routing-concepts.md

Index routes represent the default child for a parent branch. Conceptually, they answer the question: what should render when the user is at the parent path itself rather than at a deeper child path? Nested routes then compose parent and child route matches into a branch. A parent can provide layout, data requirements, or context, while a child contributes the more specific screen. Matching is therefore not a flat lookup table; it produces an ordered set of matches that describes how the shell, layout routes, and leaf route should work together.

Sources: docs/router/routing/routing-concepts.md

Route Trees, Definitions, and Type Safety

The application route tree is built from route definitions, whether those definitions are authored directly or generated from file-based routing conventions. Each route definition identifies where the route belongs in the tree and what behavior it contributes. In file-based routing, the route file path and the createFileRoute path argument become part of a generated map. That map is what lets TanStack Router expose typed navigation, typed params, typed search, and typed loader data without requiring every link or hook call to repeat route knowledge by hand.

Sources: docs/router/routing/routing-concepts.md

This design explains why the path argument in createFileRoute is treated as tool-managed rather than purely developer-authored boilerplate. The route file, URL pattern, and generated route tree must agree. If they do, navigation APIs can autocomplete known destinations, links can validate params and search objects, loaders can be associated with their route IDs, and route components can read the data and context that belong to their match. The result is a router that uses the same contract for rendering and for day-to-day application APIs.

Sources: docs/router/routing/routing-concepts.md

System-to-Code Mapping

ConceptSource-backed API or conventionWhat it contributes
File routecreateFileRoute(path)(options)Defines a non-root route and connects a route file to typed route generation.
Root routecreateRootRoute()Creates the always-matched top-level parent route.
Root route with contextcreateRootRouteWithContext<TContext>()Types shared router context such as a query client.
Basic routecreateFileRoute('/about')({ component })Matches a concrete pathname and renders the configured component.
Tool-managed pathBundler Plugin or Router CLI updates the path argumentKeeps route files, generated types, and navigation APIs aligned.

Practical Next Steps

When designing a new TanStack Router app, start by identifying the route tree rather than only listing pages. Decide what belongs in the root route, which screens are basic leaf routes, which URLs need index behavior, and which parents should act as shared layouts. Then let file-based routing and the router tooling maintain the path-to-file relationship, because that generated relationship is what powers the type-safe APIs used throughout the application. After this page, continue with layout and outlet documentation to see how matched branches compose visible UI.

Sources: docs/router/routing/routing-concepts.md