Most of the TanStack Router documentation is written for file-based routing and is intended to help you understand in more detail how to configure file-based routing and the technical details behind how it works. While file-based routing is the preferred and recommended way to configure TanStack Router, you can also use code-based routing if you prefer.
[!NOTE] 🧠 If you are already familiar with how file-based routing works and are looking for setup instructions, you can skip ahead to the Installation section. Or if you looking for the configuration options, skip ahead to the Options section.
File-based routing is a way to configure your routes using the filesystem. Instead of defining your route structure via code, you can define your routes using a series of files and directories that represent the route hierarchy of your application. This brings a number of benefits:
/
s or .
s?While directories have long been used to represent route hierarchy, file-based routing introduces an additional concept of using the .
character in the file-name to denote a route nesting. This allows you to avoid creating directories for few deeply nested routes and continue to use directories for wider route hierarchies. Let's take a look at some examples!
Directories can be used to denote route hierarchy, which can be useful for organizing multiple routes into logical groups and also cutting down on the filename length for large groups of deeply nested routes:
Filename | Route Path | Component Output |
---|---|---|
ʦ __root.tsx | <Root> | |
ʦ index.tsx | / (exact) | <Root><RootIndex> |
ʦ about.tsx | /about | <Root><About> |
ʦ posts.tsx | /posts | <Root><Posts> |
📂 posts | ||
┄ ʦ index.tsx | /posts (exact) | <Root><Posts><PostsIndex> |
┄ ʦ $postId.tsx | /posts/$postId | <Root><Posts><Post> |
📂 posts_ | ||
┄ 📂 $postId | ||
┄ ┄ ʦ edit.tsx | /posts/$postId/edit | <Root><EditPost> |
ʦ settings.tsx | /settings | <Root><Settings> |
📂 settings | <Root><Settings> | |
┄ ʦ profile.tsx | /settings/profile | <Root><Settings><Profile> |
┄ ʦ notifications.tsx | /settings/notifications | <Root><Settings><Notifications> |
ʦ _layout.tsx | <Root><Layout> | |
📂 _layout | ||
┄ ʦ layout-a.tsx | /layout-a | <Root><Layout><LayoutA> |
┄ ʦ layout-b.tsx | /layout-b | <Root><Layout><LayoutB> |
📂 files | ||
┄ ʦ $.tsx | /files/$ | <Root><Files> |
Flat routing gives you the ability to use .
s to denote route nesting levels. This can be useful when you have a large number of uniquely deeply nested routes and want to avoid creating directories for each one:
Filename | Route Path | Component Output |
---|---|---|
ʦ __root.tsx | <Root> | |
ʦ index.tsx | / (exact) | <Root><RootIndex> |
ʦ about.tsx | /about | <Root><About> |
ʦ posts.tsx | /posts | <Root><Posts> |
ʦ posts.index.tsx | /posts (exact) | <Root><Posts><PostsIndex> |
ʦ posts.$postId.tsx | /posts/$postId | <Root><Posts><Post> |
ʦ posts_.$postId.edit.tsx | /posts/$postId/edit | <Root><EditPost> |
ʦ settings.tsx | /settings | <Root><Settings> |
ʦ settings.profile.tsx | /settings/profile | <Root><Settings><Profile> |
ʦ settings.notifications.tsx | /settings/notifications | <Root><Settings><Notifications> |
ʦ _layout.tsx | <Root><Layout> | |
ʦ _layout.layout-a.tsx | /layout-a | <Root><Layout><LayoutA> |
ʦ _layout.layout-b.tsx | /layout-b | <Root><Layout><LayoutB> |
ʦ files.$.tsx | /files/$ | <Root><Files> |
It's extremely likely that a 100% directory or flat route structure won't be the best fit for your project, which is why TanStack Router allows you to mix both flat and directory routes together to create a route tree that uses the best of both worlds where it makes sense:
Filename | Route Path | Component Output |
---|---|---|
ʦ __root.tsx | <Root> | |
ʦ index.tsx | / (exact) | <Root><RootIndex> |
ʦ about.tsx | /about | <Root><About> |
ʦ posts.tsx | /posts | <Root><Posts> |
📂 posts | ||
┄ ʦ index.tsx | /posts (exact) | <Root><Posts><PostsIndex> |
┄ ʦ $postId.tsx | /posts/$postId | <Root><Posts><Post> |
┄ ʦ $postId.edit.tsx | /posts/$postId/edit | <Root><Posts><Post><EditPost> |
ʦ settings.tsx | /settings | <Root><Settings> |
ʦ settings.profile.tsx | /settings/profile | <Root><Settings><Profile> |
ʦ settings.notifications.tsx | /settings/notifications | <Root><Settings><Notifications> |
Both flat and directory routes can be mixed together to create a route tree that uses the best of both worlds where it makes sense.
[!TIP] If you find the need to customize the location of your route files or completely override the discovery of routes, you can use Virtual File Routes to programmatically build your route tree while still getting the awesome benefits of file-based routing.
Dynamic path params can be used in both flat and directory routes to create routes that can match a dynamic segment of the URL path. Dynamic path params are denoted by the $
character in the filename:
Filename | Route Path | Component Output |
---|---|---|
... | ... | ... |
ʦ posts.$postId.tsx | /posts/$postId | <Root><Posts><Post><Post> |
We'll learn more about dynamic path params in the Path Params guide.
Pathless routes wrap child routes with either logic or a component without requiring a URL path. Non-path routes are denoted by the _
character in the filename:
Filename | Route Path | Component Output |
---|---|---|
ʦ _app.tsx | ||
ʦ _app.a.tsx | /a | <Root><App><A> |
ʦ _app.b.tsx | /b | <Root><App><B> |
To learn more about pathless routes, see the Routing Concepts - Pathless Routes guide.
File-based routing requires that you follow a few simple file naming conventions to ensure that your routes are generated correctly. The concepts these conventions enable are covered in detail in the Route Trees & Nesting guide.
[!IMPORTANT] Routes starting with
/api
are reserved and cannot not be used for file-based routing. These routes are reserved for future use by the TanStack Start for API routes. If you need to use routes starting with/api
when using TanStack Router with file-based routing, then you'll need to configure theapiBase
option to a different value.
💡 Remember: The file-naming conventions for your project could be affected by what options are configured in your
tsr.config.json
. By default, therouteFileIgnorePrefix
option is set to-
, as such files and directories starting with-
will not be considered for routing.
__root.tsx
__root.tsx
and must be placed in the root of the configured routesDirectory
..
Separator
.
character to denote a nested route. For example, blog.post
will be generated as a child of blog
.$
Token
$
token are parameterized and will extract the value from the URL pathname as a route param
._
Prefix
_
prefix are considered layout-routes and will not be used when matching its child routes against the URL pathname._
Suffix
_
suffix exclude the route from being nested under any parent routes.(folder)
folder name pattern:
index
Token
index
token (but before any file types) will be used to match the parent route when the URL pathname matches the parent route exactly.
This can be configured via the indexToken
configuration option, see options..route.tsx
File Type
route
suffix can be used to create a route file at the directory's path. For example, blog.post.route.tsx
or blog/post/route.tsx
can be used at the route file for the /blog/post
route.
This can be configured via the routeToken
configuration option, see options..lazy.tsx
File Type
lazy
suffix can be used to code-split components for a route. For example, blog.post.lazy.tsx
will be used as the component for the blog.post
route.To get started with file-based routing, you'll need to configure your project's bundler to use the TanStack Router Plugin or the TanStack Router CLI.
To enable file-based routing, you'll need to be using React with a supported bundler. TanStack Router currently has support for the following bundlers:
When using using TanStack Router's file-based routing through one of the supported bundlers, our plugin will automatically generate your route configuration through your bundler's dev and build processes. It is the easiest way to use TanStack Router's route generation features.
If your bundler is not yet supported, you can reach out to us on Discord or GitHub to let us know. Till then, fear not! You can still use the @tanstack/router-cli
package to generate your route tree file.
To use file-based routing with Vite, you'll need to install the @tanstack/router-plugin
package.
npm install -D @tanstack/router-plugin
Once installed, you'll need to add the plugin to your Vite configuration.
// vite.config.tsimport { defineConfig } from 'vite'import viteReact from '@vitejs/plugin-react'import { TanStackRouterVite } from '@tanstack/router-plugin/vite'
// https://vitejs.dev/config/export default defineConfig({ plugins: [ TanStackRouterVite(), viteReact(), // ... ],})
Or, you can clone our Quickstart Vite example and get started.
[!WARNING] If you are using the older
@tanstack/router-vite-plugin
package, you can still continue to use it, as it will be aliased to the@tanstack/router-plugin/vite
package. However, we would recommend using the@tanstack/router-plugin
package directly.
Now that you've added the plugin to your Vite configuration, you're all set to start using file-based routing with TanStack Router.
You shouldn't forget to ignore the generated route tree file. Head over to the Ignoring the generated route tree file section to learn more.
To use file-based routing with Rspack or Rsbuild, you'll need to install the @tanstack/router-plugin
package.
npm install -D @tanstack/router-plugin
Once installed, you'll need to add the plugin to your configuration.
// rsbuild.config.tsimport { defineConfig } from '@rsbuild/core'import { pluginReact } from '@rsbuild/plugin-react'import { TanStackRouterRspack } from '@tanstack/router-plugin/rspack'
export default defineConfig({ plugins: [pluginReact()], tools: { rspack: { plugins: [TanStackRouterRspack()], }, },})
Or, you can clone our Quickstart Rspack/Rsbuild example and get started.
Now that you've added the plugin to your Rspack/Rsbuild configuration, you're all set to start using file-based routing with TanStack Router.
You shouldn't forget to ignore the generated route tree file. Head over to the Ignoring the generated route tree file section to learn more.
To use file-based routing with Webpack, you'll need to install the @tanstack/router-plugin
package.
npm install -D @tanstack/router-plugin
Once installed, you'll need to add the plugin to your configuration.
// webpack.config.tsimport { TanStackRouterWebpack } from '@tanstack/router-plugin/webpack'
export default { plugins: [TanStackRouterWebpack()],}
Or, you can clone our Quickstart Webpack example and get started.
Now that you've added the plugin to your Webpack configuration, you're all set to start using file-based routing with TanStack Router.
You shouldn't forget to ignore the generated route tree file. Head over to the Ignoring the generated route tree file section to learn more.
To use file-based routing with Esbuild, you'll need to install the @tanstack/router-plugin
package.
npm install -D @tanstack/router-plugin
Once installed, you'll need to add the plugin to your configuration.
// esbuild.config.jsimport { TanStackRouterEsbuild } from '@tanstack/router-plugin/esbuild'
export default { // ... plugins: [TanStackRouterEsbuild()],}
Or, you can clone our Quickstart Esbuild example and get started.
Now that you've added the plugin to your Esbuild configuration, you're all set to start using file-based routing with TanStack Router.
You shouldn't forget to ignore the generated route tree file. Head over to the Ignoring the generated route tree file section to learn more.
To use file-based routing with the TanStack Router CLI, you'll need to install the @tanstack/router-cli
package.
npm install -D @tanstack/router-cli
Once installed, you'll need to amend your your scripts in your package.json
for the CLI to watch
and generate
files.
{ "scripts": { "generate-routes": "tsr generate", "watch-routes": "tsr watch", "build": "npm run generate-routes && ...", "dev": "npm run watch-routes && ..." }}
You shouldn't forget to ignore the generated route tree file. Head over to the Ignoring the generated route tree file section to learn more.
With the CLI installed, the following commands are made available via the tsr
command
generate
commandGenerates the routes for a project based on the provided configuration.
tsr generate
watch
commandContinuously watches the specified directories and regenerates routes as needed.
Usage:
tsr watch
With file-based routing enabled, whenever you start your application in development mode, TanStack Router will watch your configured routesDirectory
and generate your route tree whenever a file is added, removed, or changed.
⚠️ Note: To disable the plugin when running tests via vitest, you can conditionally add it based on the current
NODE_ENV
:
// vite.config.tsimport { defineConfig } from 'vite'import viteReact from '@vitejs/plugin-react'import { TanStackRouterVite } from '@tanstack/router-vite-plugin'
// vitest automatically sets NODE_ENV to 'test' when running testsconst isTest = process.env.NODE_ENV === 'test'
// https://vitejs.dev/config/export default defineConfig({ plugins: [ !isTest && TanStackRouterVite(), viteReact(), // ... ],})
If your project is configured to use a linter and/or formatter, you may want to ignore the generated route tree file. This file is managed by TanStack Router and therefore shouldn't be changed by your linter or formatter.
Here are some resources to help you ignore the generated route tree file:
If you are using VSCode, you can also add the following to your .vscode/settings.json
file to exclude the generated route tree file from the editor's file watcher:
{ "files.watcherExclude": { "**/routeTree.gen.ts": true }}
File-based routing comes with some sane defaults that should work for most projects:
{ "routesDirectory": "./src/routes", "generatedRouteTree": "./src/routeTree.gen.ts", "routeFileIgnorePrefix": "-", "quoteStyle": "single"}
If these defaults work for your project, you don't need to configure anything at all! However, if you need to customize the configuration, you can do so by creating a tsr.config.json
file in the root of your project directory.
tsr.config.json
file in the root of your project directory.The following options are available for configuration via the tsr.config.json
file:
[!IMPORTANT] Do not set the
routeFilePrefix
,routeFileIgnorePrefix
, orrouteFileIgnorePattern
options, to match any of the tokens used in the file-naming conventions section.
routeFilePrefix
routeFileIgnorePrefix
-
) Route files and directories that start with this string will be ignored. By default this is set to -
to allow for the use of directories to house related files that do not contain any route files.routeFileIgnorePattern
.((css|const).ts)|test-page
will ignore files / directories with names containing .css.ts
, .const.ts
or test-page
.indexToken
'index'
) allows to customize the index
Token file naming convention.routeToken
'route'
) allows to customize the route
Token file naming convention.routesDirectory
generatedRouteTree
autoCodeSplitting
false
)true
, all non-critical route configuration items will be automatically code-split.quoteStyle
single
) whether to use single
or double
quotes when formatting the generated route tree file.`semicolons
false
) whether to use semicolons in the generated route tree file.apiBase
/api
.disableTypes
false
) whether to disable generating types for the route treetrue
, the generated route tree will not include any types.true
and the generatedRouteTree
file ends with .ts
or .tsx
, the generated route tree will be written as a .js
file instead.addExtensions
false
) add file extensions to the route names in the generated route treedisableLogging
false
) disables logging for the route generation processrouteTreeFileHeader
[ '/* eslint-disable */', '// @ts-nocheck', '// noinspection JSUnusedGlobalSymbols']
routeTreeFileFooter
[]
disableManifestGeneration
false
) disables generating the route tree manifestVia the routeFilePrefix
and routeFileIgnorePrefix
options, the CLI can be configured to only include files and directories that start with a specific prefix, or to ignore files and directories that start with a specific prefix. This is especially useful when mixing non-route files with route files in the same directory, or when using a flat structure and wanting to exclude certain files from routing.
To only consider files and directories that start with ~
for routing, the following configuration can be used:
🧠 A prefix of
~
is generally recommended when using this option. Not only is this symbol typically associated with the home-folder navigation in unix-based systems, but it is also a valid character for use in filenames and urls that will typically force the file to the top of a directory for easier visual indication of routes.
{ "routeFilePrefix": "~", "routesDirectory": "./src/routes", "generatedRouteTree": "./src/routeTree.gen.ts"}
With this configuration, the Posts.tsx
, Post.tsx
, and PostEditor.tsx
files will be ignored during route generation.
~__root.tsx~posts.tsx~posts ~index.tsx ~$postId.tsx ~$postId ~edit.tsx PostEditor.tsx Post.tsxPosts.tsx
It's also common to use directories to house related files that do not contain any route files:
~__root.tsx~posts.tsx~posts ~index.tsx ~$postId.tsx ~$postId ~edit.tsx components PostEditor.tsx components Post.tsxcomponents Posts.tsxutils Posts.tsx
To ignore files and directories that start with -
for routing, the following configuration can be used:
🧠 A prefix of
-
is generally recommended when using this option since the minus symbol is typically associated with removal or exclusion.
{ "routeFileIgnorePrefix": "-", "routesDirectory": "./src/routes", "generatedRouteTree": "./src/routeTree.gen.ts"}
With this configuration, the Posts.tsx
, Post.tsx
, and PostEditor.tsx
files will be ignored during route generation.
__root.tsxposts.tsxposts index.tsx $postId.tsx $postId edit.tsx -PostEditor.tsx -Post.tsx-Posts.tsx
It's also common to use ignored directories to house related files that do not contain any route files:
__root.tsxposts.tsxposts index.tsx $postId.tsx $postId edit.tsx -components PostEditor.tsx -components Post.tsx-components Posts.tsx-utils Posts.tsx
Your weekly dose of JavaScript news. Delivered every Monday to over 100,000 devs, for free.