File-Based Routing
File-based routing is the workflow where route modules are discovered from files under a route directory and then assembled into a typed route tree for the application. In TanStack Router, this workflow is not just a naming convenience. It is the mechanism that lets route files keep strong TypeScript relationships with paths, params, search validation, loaders, and navigation APIs while still letting developers organize routes as normal source files. The public documentation describes the file-based routing API as flexible and configurable, and the source packages show that the workflow is split between configuration, route discovery, route tree generation, and optional virtual route declarations.
Sources: docs/router/api/file-based-routing.md, packages/router-generator/src/index.ts, packages/virtual-file-routes/src/index.ts
The most important mental model is that a file route is both a module and a node in the router tree. A route file exports the route definition used by the framework package, while the generator writes a routeTree.gen.ts file that imports those route modules and connects them. Official Router guidance explains why createFileRoute receives a path string even though the file already has a location: TypeScript needs a stable literal route identity, and the Router plugin or CLI manages that value as files are created, moved, or renamed. The generated tree is therefore part of the type-safety contract, not a disposable build artifact.
Sources: docs/router/api/file-based-routing.md, packages/router-plugin/README.md, packages/router-generator/src/index.ts
Purpose and Scope
Use this page when you need to understand how TanStack Router turns files into typed routes, how to configure the filesystem conventions, and which repository packages own each piece of the pipeline. It focuses on the source-backed public API around file-based routing configuration, the @tanstack/router-plugin package that integrates generation with a bundler-driven workflow, the @tanstack/router-generator entrypoint that exposes configuration and discovery primitives, and the @tanstack/virtual-file-routes entrypoint for declaring route trees without matching every node to a physical file.
Sources: docs/router/api/file-based-routing.md, packages/router-plugin/README.md, packages/router-generator/src/index.ts, packages/virtual-file-routes/src/index.ts
This page does not replace the broader routing concepts guide. Instead, it connects those concepts to repository surfaces that developers configure directly. A root route still represents the always-matched top of the tree, layout route files still provide parent UI for children, and index routes still represent a directory or path default. File-based routing adds a repeatable convention layer around those concepts so the router can infer route hierarchy from file names and directories, then generate code that application code imports when creating the router.
Sources: docs/router/api/file-based-routing.md
Relevant Source Files
docs/router/api/file-based-routing.md— Documents the file-based routing configuration options, required defaults, route-file filtering options, formatting controls, and the warning about conflicting custom prefixes or tokens with naming conventions.packages/router-plugin/README.md— Identifies the@tanstack/router-pluginpackage, its installation command, and its role as the bundler plugin users install for file-based routing workflows.packages/router-generator/src/index.ts— Re-exports the generator public API, including config schemas, config resolution helpers, theGeneratorclass, file event types, route-node types, route discovery functions for physical and virtual filesystems, and route path utility functions.packages/virtual-file-routes/src/index.ts— Re-exports the public virtual route declaration API, includingrootRoute,index,route,layout,physical, and thedefineVirtualSubtreeConfighelper with its associated types.
Core Primitives
The file-based routing API starts with two required paths. routesDirectory points to the directory where route files live, relative to the current working directory, and defaults to ./src/routes. generatedRouteTree points to the generated file where the assembled route tree is saved, also relative to the current working directory, and defaults to ./src/routeTree.gen.ts. The documentation states that neither required value can be an empty string or undefined; when disableTypes is enabled, the generated file is written with a JavaScript extension instead of TypeScript.
Sources: docs/router/api/file-based-routing.md
The generator package exports the programmatic building blocks behind that configuration. configSchema, baseConfigSchema, getConfig, and resolveConfigPath form the public configuration surface. Generator, FileEventType, FileEvent, and GeneratorEvent describe the generation process and its events. Route discovery is exposed as physicalGetRouteNodes and virtualGetRouteNodes, which makes the distinction explicit: the same generated tree concept can be fed by files on disk or by virtual route configuration. Utility exports such as inferFullPath, determineInitialRoutePath, routePathToVariable, and checkRouteFullPathUniqueness show that path normalization, variable naming, and uniqueness checks are first-class generator responsibilities.
Sources: packages/router-generator/src/index.ts
Virtual file routes are the extension point for teams that want typed route-tree generation without encoding the entire hierarchy in physical filenames. The virtual-file-routes package exports route-building functions named rootRoute, index, route, layout, and physical. These names mirror Router concepts: a virtual subtree can declare a root, normal path routes, index routes, layout routes, and a bridge back to a physical subtree. defineVirtualSubtreeConfig then packages those declarations as configuration that the generator can consume through the virtualRouteConfig option documented by the file-based routing API.
Sources: docs/router/api/file-based-routing.md, packages/virtual-file-routes/src/index.ts
Configuration Reference
The configuration surface is intentionally practical: it controls where routes are found, where generated output is written, which files count as routes, how route-tree code is emitted, and whether advanced generation features are enabled. The documented options include routesDirectory, generatedRouteTree, virtualRouteConfig, routeFilePrefix, routeFileIgnorePrefix, routeFileIgnorePattern, indexToken, routeToken, quoteStyle, semicolons, autoCodeSplitting, disableTypes, addExtensions, disableLogging, routeTreeFileHeader, routeTreeFileFooter, enableRouteTreeFormatting, and tmpDir. Treat these options as build-time inputs: changing them changes what route modules are discovered and how the generated tree is written.
Sources: docs/router/api/file-based-routing.md
| Option | What it controls | Source-backed default or behavior |
|---|---|---|
routesDirectory | Physical route file root | Defaults to ./src/routes and must not be empty or undefined. |
generatedRouteTree | Generated route tree output path | Defaults to ./src/routeTree.gen.ts; uses .js when disableTypes is true. |
virtualRouteConfig | Virtual File Routes input | Defaults to undefined and connects to the Virtual File Routes feature. |
routeFilePrefix | Opt-in prefix for route files | Defaults to an empty value, meaning all route-directory files are considered unless otherwise ignored. |
routeFileIgnorePrefix | Prefix for ignored route files or directories | Defaults to -, enabling colocated non-route files such as -components. |
routeFileIgnorePattern | Regex-style ignore pattern | Can ignore names such as CSS modules, constants files, or test pages. |
routeToken | Layout route file token | Defaults to route; examples include posts.tsx, posts.route.tsx, and posts/route.tsx mapping to the same runtime URL. |
A key safety note in the documentation is that routeFilePrefix, routeFileIgnorePrefix, and routeFileIgnorePattern should not be configured to match tokens used by the file naming conventions. This matters because the generator interprets filenames semantically. If a custom ignore prefix overlaps with a layout, index, pathless, or other convention token, a file might be skipped, misclassified, or assigned a different route identity than intended. The safest customization strategy is to start from the defaults, add only one filter at a time, and verify the generated route tree after every convention change.
Sources: docs/router/api/file-based-routing.md
System-to-Code Mapping
The system has four reader-visible layers. The docs page defines the public options and defaults. The plugin package gives application projects the installable bundler integration, with the README naming @tanstack/router-plugin and showing npm install -D @tanstack/router-plugin. The generator package exposes the reusable engine for config loading, route discovery, transformation, utility normalization, and event reporting. The virtual-file-routes package exposes a declarative API for route trees that are not purely discovered from a directory. Together, these layers keep the developer workflow simple while keeping the implementation reusable across CLI, bundler, physical, and virtual inputs.
Sources: docs/router/api/file-based-routing.md, packages/router-plugin/README.md, packages/router-generator/src/index.ts, packages/virtual-file-routes/src/index.ts
| Layer | Public entry points | Responsibility |
|---|---|---|
| Documentation | docs/router/api/file-based-routing.md | Defines configuration names, defaults, warnings, and examples. |
| Bundler integration | @tanstack/router-plugin | Installs as a development dependency and connects app builds to route generation. |
| Generator engine | Generator, getConfig, physicalGetRouteNodes, virtualGetRouteNodes | Resolves configuration, discovers route nodes, and emits generated tree code. |
| Virtual route declarations | rootRoute, route, layout, index, physical, defineVirtualSubtreeConfig | Declares generated route subtrees outside a fully physical file layout. |
Execution Flow
In a typical app, the developer creates route modules under src/routes, imports the generated route tree from src/routeTree.gen.ts, and lets the plugin or CLI keep that generated file synchronized. When file-based routing is enabled, the generator reads configuration, walks the physical route directory unless virtual configuration is supplied, derives route nodes, checks full-path uniqueness, formats output according to code style options, and writes the tree only when the contents differ. The exported utility names in the generator entrypoint make these responsibilities visible even though most application developers interact with them indirectly.
Sources: docs/router/api/file-based-routing.md, packages/router-generator/src/index.ts
A minimal conceptual setup looks like this: install the plugin as a development dependency, keep routes under the default directory, and import the generated tree from the default generated file. The plugin README intentionally points readers back to the official file-based routing and Router CLI usage docs, which means the package is not a standalone routing runtime. It is build tooling that supports the Router runtime packages by ensuring the route tree and file route path literals stay current as the filesystem changes.
Sources: packages/router-plugin/README.md
npm install -D @tanstack/router-pluginsrc/routes
├── __root.tsx
├── index.tsx
└── posts
├── -components
│ └── Post.tsx
├── index.tsx
└── route.tsx
src/routeTree.gen.tsThe ignored -components directory in this example follows the documented default routeFileIgnorePrefix of -. That convention is useful because route files often need nearby UI components, schemas, helpers, or tests, but not every colocated module should become a route. If your project uses another colocation convention, prefer routeFileIgnorePattern for narrow exclusions or routeFilePrefix for an explicit opt-in style. After changing either setting, inspect the generated tree and route URLs to ensure the filter did not accidentally hide layout or index route modules.
Sources: docs/router/api/file-based-routing.md
Practical Guidance and Next Steps
Choose physical file-based routing when your route hierarchy maps naturally to folders and filenames. Choose virtual file routes when the route tree needs to be generated from another structure, shared between packages, or partially declared in code while still composing with physical subtrees. In both cases, preserve the generated route tree as the contract between the build step and the runtime router. Do not hand-edit generated route paths as a long-term fix; instead, adjust route files, route naming conventions, or generator configuration so the next generation pass produces the intended tree.
Sources: docs/router/api/file-based-routing.md, packages/router-generator/src/index.ts, packages/virtual-file-routes/src/index.ts
For the next step, read the routing concepts material alongside this page: it explains root routes, layout routes, file routes, and why createFileRoute receives a route path literal. Then move to route trees, layouts, and outlets to understand how generated parent-child relationships render UI. If you are configuring a build, continue with the router plugin and route generation page. If you are debugging unexpected routes, compare routesDirectory, ignore settings, routeToken, and generatedRouteTree against the generated file before investigating runtime navigation code.
Sources: docs/router/api/file-based-routing.md, packages/router-plugin/README.md, packages/router-generator/src/index.ts