UNPKG

@tanstack/react-router

Version:

Modern and scalable routing for React applications

1 lines 77.8 kB
declare const _default: "# Code-Based Routing\n\n> [!TIP]\n> Code-based routing is not recommended for most applications. It is recommended to use [File-Based Routing](../file-based-routing.md) instead.\n\n## \u26A0\uFE0F Before You Start\n\n- If you're using [File-Based Routing](../file-based-routing.md), **skip this guide**.\n- If you still insist on using code-based routing, you must read the [Routing Concepts](../routing-concepts.md) guide first, as it also covers core concepts of the router.\n\n## Route Trees\n\nCode-based routing is no different from file-based routing in that it uses the same route tree concept to organize, match and compose matching routes into a component tree. The only difference is that instead of using the filesystem to organize your routes, you use code.\n\nLet's consider the same route tree from the [Route Trees & Nesting](../route-trees.md#route-trees) guide, and convert it to code-based routing:\n\nHere is the file-based version:\n\n```\nroutes/\n\u251C\u2500\u2500 __root.tsx\n\u251C\u2500\u2500 index.tsx\n\u251C\u2500\u2500 about.tsx\n\u251C\u2500\u2500 posts/\n\u2502 \u251C\u2500\u2500 index.tsx\n\u2502 \u251C\u2500\u2500 $postId.tsx\n\u251C\u2500\u2500 posts.$postId.edit.tsx\n\u251C\u2500\u2500 settings/\n\u2502 \u251C\u2500\u2500 profile.tsx\n\u2502 \u251C\u2500\u2500 notifications.tsx\n\u251C\u2500\u2500 _pathlessLayout.tsx\n\u251C\u2500\u2500 _pathlessLayout/\n\u2502 \u251C\u2500\u2500 route-a.tsx\n\u251C\u2500\u2500 \u251C\u2500\u2500 route-b.tsx\n\u251C\u2500\u2500 files/\n\u2502 \u251C\u2500\u2500 $.tsx\n```\n\nAnd here is a summarized code-based version:\n\n```tsx\nimport { createRootRoute, createRoute } from '@tanstack/react-router'\n\nconst rootRoute = createRootRoute()\n\nconst indexRoute = createRoute({\n getParentRoute: () => rootRoute,\n path: '/',\n})\n\nconst aboutRoute = createRoute({\n getParentRoute: () => rootRoute,\n path: 'about',\n})\n\nconst postsRoute = createRoute({\n getParentRoute: () => rootRoute,\n path: 'posts',\n})\n\nconst postsIndexRoute = createRoute({\n getParentRoute: () => postsRoute,\n path: '/',\n})\n\nconst postRoute = createRoute({\n getParentRoute: () => postsRoute,\n path: '$postId',\n})\n\nconst postEditorRoute = createRoute({\n getParentRoute: () => rootRoute,\n path: 'posts/$postId/edit',\n})\n\nconst settingsRoute = createRoute({\n getParentRoute: () => rootRoute,\n path: 'settings',\n})\n\nconst profileRoute = createRoute({\n getParentRoute: () => settingsRoute,\n path: 'profile',\n})\n\nconst notificationsRoute = createRoute({\n getParentRoute: () => settingsRoute,\n path: 'notifications',\n})\n\nconst pathlessLayoutRoute = createRoute({\n getParentRoute: () => rootRoute,\n id: 'pathlessLayout',\n})\n\nconst pathlessLayoutARoute = createRoute({\n getParentRoute: () => pathlessLayoutRoute,\n path: 'route-a',\n})\n\nconst pathlessLayoutBRoute = createRoute({\n getParentRoute: () => pathlessLayoutRoute,\n path: 'route-b',\n})\n\nconst filesRoute = createRoute({\n getParentRoute: () => rootRoute,\n path: 'files/$',\n})\n```\n\n## Anatomy of a Route\n\nAll other routes other than the root route are configured using the `createRoute` function:\n\n```tsx\nconst route = createRoute({\n getParentRoute: () => rootRoute,\n path: '/posts',\n component: PostsComponent,\n})\n```\n\nThe `getParentRoute` option is a function that returns the parent route of the route you're creating.\n\n**\u2753\u2753\u2753 \"Wait, you're making me pass the parent route for every route I make?\"**\n\nAbsolutely! The reason for passing the parent route has **everything to do with the magical type safety** of TanStack Router. Without the parent route, TypeScript would have no idea what types to supply your route with!\n\n> [!IMPORTANT]\n> For every route that **NOT** the **Root Route** or a **Pathless Layout Route**, a `path` option is required. This is the path that will be matched against the URL pathname to determine if the route is a match.\n\nWhen configuring route `path` option on a route, it ignores leading and trailing slashes (this does not include \"index\" route paths `/`). You can include them if you want, but they will be normalized internally by TanStack Router. Here is a table of valid paths and what they will be normalized to:\n\n| Path | Normalized Path |\n| -------- | --------------- |\n| `/` | `/` |\n| `/about` | `about` |\n| `about/` | `about` |\n| `about` | `about` |\n| `$` | `$` |\n| `/$` | `$` |\n| `/$/` | `$` |\n\n## Manually building the route tree\n\nWhen building a route tree in code, it's not enough to define the parent route of each route. You must also construct the final route tree by adding each route to its parent route's `children` array. This is because the route tree is not built automatically for you like it is in file-based routing.\n\n```tsx\n/* prettier-ignore */\nconst routeTree = rootRoute.addChildren([\n indexRoute,\n aboutRoute,\n postsRoute.addChildren([\n postsIndexRoute,\n postRoute,\n ]),\n postEditorRoute,\n settingsRoute.addChildren([\n profileRoute,\n notificationsRoute,\n ]),\n pathlessLayoutRoute.addChildren([\n pathlessLayoutARoute,\n pathlessLayoutBRoute,\n ]),\n filesRoute.addChildren([\n fileRoute,\n ]),\n])\n/* prettier-ignore-end */\n```\n\nBut before you can go ahead and build the route tree, you need to understand how the Routing Concepts for Code-Based Routing work.\n\n## Routing Concepts for Code-Based Routing\n\nBelieve it or not, file-based routing is really a superset of code-based routing and uses the filesystem and a bit of code-generation abstraction on top of it to generate this structure you see above automatically.\n\nWe're going to assume you've read the [Routing Concepts](../routing-concepts.md) guide and are familiar with each of these main concepts:\n\n- The Root Route\n- Basic Routes\n- Index Routes\n- Dynamic Route Segments\n- Splat / Catch-All Routes\n- Layout Routes\n- Pathless Routes\n- Non-Nested Routes\n\nNow, let's take a look at how to create each of these route types in code.\n\n## The Root Route\n\nCreating a root route in code-based routing is thankfully the same as doing so in file-based routing. Call the `createRootRoute()` function.\n\nUnlike file-based routing however, you do not need to export the root route if you don't want to. It's certainly not recommended to build an entire route tree and application in a single file (although you can and we do this in the examples to demonstrate routing concepts in brevity).\n\n```tsx\n// Standard root route\nimport { createRootRoute } from '@tanstack/react-router'\n\nconst rootRoute = createRootRoute()\n\n// Root route with Context\nimport { createRootRouteWithContext } from '@tanstack/react-router'\nimport type { QueryClient } from '@tanstack/react-query'\n\nexport interface MyRouterContext {\n queryClient: QueryClient\n}\nconst rootRoute = createRootRouteWithContext<MyRouterContext>()\n```\n\nTo learn more about Context in TanStack Router, see the [Router Context](../../guide/router-context.md) guide.\n\n## Basic Routes\n\nTo create a basic route, simply provide a normal `path` string to the `createRoute` function:\n\n```tsx\nconst aboutRoute = createRoute({\n getParentRoute: () => rootRoute,\n path: 'about',\n})\n```\n\nSee, it's that simple! The `aboutRoute` will match the URL `/about`.\n\n## Index Routes\n\nUnlike file-based routing, which uses the `index` filename to denote an index route, code-based routing uses a single slash `/` to denote an index route. For example, the `posts.index.tsx` file from our example route tree above would be represented in code-based routing like this:\n\n```tsx\nconst postsRoute = createRoute({\n getParentRoute: () => rootRoute,\n path: 'posts',\n})\n\nconst postsIndexRoute = createRoute({\n getParentRoute: () => postsRoute,\n // Notice the single slash `/` here\n path: '/',\n})\n```\n\nSo, the `postsIndexRoute` will match the URL `/posts/` (or `/posts`).\n\n## Dynamic Route Segments\n\nDynamic route segments work exactly the same in code-based routing as they do in file-based routing. Simply prefix a segment of the path with a `$` and it will be captured into the `params` object of the route's `loader` or `component`:\n\n```tsx\nconst postIdRoute = createRoute({\n getParentRoute: () => postsRoute,\n path: '$postId',\n // In a loader\n loader: ({ params }) => fetchPost(params.postId),\n // Or in a component\n component: PostComponent,\n})\n\nfunction PostComponent() {\n const { postId } = postIdRoute.useParams()\n return <div>Post ID: {postId}</div>\n}\n```\n\n> [!TIP]\n> If your component is code-split, you can use the [getRouteApi function](../../guide/code-splitting.md#manually-accessing-route-apis-in-other-files-with-the-getrouteapi-helper) to avoid having to import the `postIdRoute` configuration to get access to the typed `useParams()` hook.\n\n## Splat / Catch-All Routes\n\nAs expected, splat/catch-all routes also work the same in code-based routing as they do in file-based routing. Simply prefix a segment of the path with a `$` and it will be captured into the `params` object under the `_splat` key:\n\n```tsx\nconst filesRoute = createRoute({\n getParentRoute: () => rootRoute,\n path: 'files',\n})\n\nconst fileRoute = createRoute({\n getParentRoute: () => filesRoute,\n path: '$',\n})\n```\n\nFor the URL `/documents/hello-world`, the `params` object will look like this:\n\n```js\n{\n '_splat': 'documents/hello-world'\n}\n```\n\n## Layout Routes\n\nLayout routes are routes that wrap their children in a layout component. In code-based routing, you can create a layout route by simply nesting a route under another route:\n\n```tsx\nconst postsRoute = createRoute({\n getParentRoute: () => rootRoute,\n path: 'posts',\n component: PostsLayoutComponent, // The layout component\n})\n\nfunction PostsLayoutComponent() {\n return (\n <div>\n <h1>Posts</h1>\n <Outlet />\n </div>\n )\n}\n\nconst postsIndexRoute = createRoute({\n getParentRoute: () => postsRoute,\n path: '/',\n})\n\nconst postsCreateRoute = createRoute({\n getParentRoute: () => postsRoute,\n path: 'create',\n})\n\nconst routeTree = rootRoute.addChildren([\n // The postsRoute is the layout route\n // Its children will be nested under the PostsLayoutComponent\n postsRoute.addChildren([postsIndexRoute, postsCreateRoute]),\n])\n```\n\nNow, both the `postsIndexRoute` and `postsCreateRoute` will render their contents inside of the `PostsLayoutComponent`:\n\n```tsx\n// URL: /posts\n<PostsLayoutComponent>\n <PostsIndexComponent />\n</PostsLayoutComponent>\n\n// URL: /posts/create\n<PostsLayoutComponent>\n <PostsCreateComponent />\n</PostsLayoutComponent>\n```\n\n## Pathless Layout Routes\n\nIn file-based routing a pathless layout route is prefixed with a `_`, but in code-based routing, this is simply a route with an `id` instead of a `path` option. This is because code-based routing does not use the filesystem to organize routes, so there is no need to prefix a route with a `_` to denote that it has no path.\n\n```tsx\nconst pathlessLayoutRoute = createRoute({\n getParentRoute: () => rootRoute,\n id: 'pathlessLayout',\n component: PathlessLayoutComponent,\n})\n\nfunction PathlessLayoutComponent() {\n return (\n <div>\n <h1>Pathless Layout</h1>\n <Outlet />\n </div>\n )\n}\n\nconst pathlessLayoutARoute = createRoute({\n getParentRoute: () => pathlessLayoutRoute,\n path: 'route-a',\n})\n\nconst pathlessLayoutBRoute = createRoute({\n getParentRoute: () => pathlessLayoutRoute,\n path: 'route-b',\n})\n\nconst routeTree = rootRoute.addChildren([\n // The pathless layout route has no path, only an id\n // So its children will be nested under the pathless layout route\n pathlessLayoutRoute.addChildren([pathlessLayoutARoute, pathlessLayoutBRoute]),\n])\n```\n\nNow both `/route-a` and `/route-b` will render their contents inside of the `PathlessLayoutComponent`:\n\n```tsx\n// URL: /route-a\n<PathlessLayoutComponent>\n <RouteAComponent />\n</PathlessLayoutComponent>\n\n// URL: /route-b\n<PathlessLayoutComponent>\n <RouteBComponent />\n</PathlessLayoutComponent>\n```\n\n## Non-Nested Routes\n\nBuilding non-nested routes in code-based routing does not require using a trailing `_` in the path, but does require you to build your route and route tree with the right paths and nesting. Let's consider the route tree where we want the post editor to **not** be nested under the posts route:\n\n- `/posts_/$postId/edit`\n- `/posts`\n - `$postId`\n\nTo do this we need to build a separate route for the post editor and include the entire path in the `path` option from the root of where we want the route to be nested (in this case, the root):\n\n```tsx\n// The posts editor route is nested under the root route\nconst postEditorRoute = createRoute({\n getParentRoute: () => rootRoute,\n // The path includes the entire path we need to match\n path: 'posts/$postId/edit',\n})\n\nconst postsRoute = createRoute({\n getParentRoute: () => rootRoute,\n path: 'posts',\n})\n\nconst postRoute = createRoute({\n getParentRoute: () => postsRoute,\n path: '$postId',\n})\n\nconst routeTree = rootRoute.addChildren([\n // The post editor route is nested under the root route\n postEditorRoute,\n postsRoute.addChildren([postRoute]),\n])\n```\n\n# File-Based Routing\n\nMost 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](../code-based-routing.md) if you prefer.\n\n## What is File-Based Routing?\n\nFile-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:\n\n- **Simplicity**: File-based routing is visually intuitive and easy to understand for both new and experienced developers.\n- **Organization**: Routes are organized in a way that mirrors the URL structure of your application.\n- **Scalability**: As your application grows, file-based routing makes it easy to add new routes and maintain existing ones.\n- **Code-Splitting**: File-based routing allows TanStack Router to automatically code-split your routes for better performance.\n- **Type-Safety**: File-based routing raises the ceiling on type-safety by generating managing type linkages for your routes, which can otherwise be a tedious process via code-based routing.\n- **Consistency**: File-based routing enforces a consistent structure for your routes, making it easier to maintain and update your application and move from one project to another.\n\n## `/`s or `.`s?\n\nWhile 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!\n\n## Directory Routes\n\nDirectories 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.\n\nSee the example below:\n\n| Filename | Route Path | Component Output |\n| ----------------------- | ------------------------- | --------------------------------- |\n| \u02A6 `__root.tsx` | | `<Root>` |\n| \u02A6 `index.tsx` | `/` (exact) | `<Root><RootIndex>` |\n| \u02A6 `about.tsx` | `/about` | `<Root><About>` |\n| \u02A6 `posts.tsx` | `/posts` | `<Root><Posts>` |\n| \uD83D\uDCC2 `posts` | | |\n| \u2504 \u02A6 `index.tsx` | `/posts` (exact) | `<Root><Posts><PostsIndex>` |\n| \u2504 \u02A6 `$postId.tsx` | `/posts/$postId` | `<Root><Posts><Post>` |\n| \uD83D\uDCC2 `posts_` | | |\n| \u2504 \uD83D\uDCC2 `$postId` | | |\n| \u2504 \u2504 \u02A6 `edit.tsx` | `/posts/$postId/edit` | `<Root><EditPost>` |\n| \u02A6 `settings.tsx` | `/settings` | `<Root><Settings>` |\n| \uD83D\uDCC2 `settings` | | `<Root><Settings>` |\n| \u2504 \u02A6 `profile.tsx` | `/settings/profile` | `<Root><Settings><Profile>` |\n| \u2504 \u02A6 `notifications.tsx` | `/settings/notifications` | `<Root><Settings><Notifications>` |\n| \u02A6 `_pathlessLayout.tsx` | | `<Root><PathlessLayout>` |\n| \uD83D\uDCC2 `_pathlessLayout` | | |\n| \u2504 \u02A6 `route-a.tsx` | `/route-a` | `<Root><PathlessLayout><RouteA>` |\n| \u2504 \u02A6 `route-b.tsx` | `/route-b` | `<Root><PathlessLayout><RouteB>` |\n| \uD83D\uDCC2 `files` | | |\n| \u2504 \u02A6 `$.tsx` | `/files/$` | `<Root><Files>` |\n| \uD83D\uDCC2 `account` | | |\n| \u2504 \u02A6 `route.tsx` | `/account` | `<Root><Account>` |\n| \u2504 \u02A6 `overview.tsx` | `/account/overview` | `<Root><Account><Overview>` |\n\n## Flat Routes\n\nFlat routing gives you the ability to use `.`s to denote route nesting levels.\n\nThis can be useful when you have a large number of uniquely deeply nested routes and want to avoid creating directories for each one:\n\nSee the example below:\n\n| Filename | Route Path | Component Output |\n| ------------------------------- | ------------------------- | --------------------------------- |\n| \u02A6 `__root.tsx` | | `<Root>` |\n| \u02A6 `index.tsx` | `/` (exact) | `<Root><RootIndex>` |\n| \u02A6 `about.tsx` | `/about` | `<Root><About>` |\n| \u02A6 `posts.tsx` | `/posts` | `<Root><Posts>` |\n| \u02A6 `posts.index.tsx` | `/posts` (exact) | `<Root><Posts><PostsIndex>` |\n| \u02A6 `posts.$postId.tsx` | `/posts/$postId` | `<Root><Posts><Post>` |\n| \u02A6 `posts_.$postId.edit.tsx` | `/posts/$postId/edit` | `<Root><EditPost>` |\n| \u02A6 `settings.tsx` | `/settings` | `<Root><Settings>` |\n| \u02A6 `settings.profile.tsx` | `/settings/profile` | `<Root><Settings><Profile>` |\n| \u02A6 `settings.notifications.tsx` | `/settings/notifications` | `<Root><Settings><Notifications>` |\n| \u02A6 `_pathlessLayout.tsx` | | `<Root><PathlessLayout>` |\n| \u02A6 `_pathlessLayout.route-a.tsx` | `/route-a` | `<Root><PathlessLayout><RouteA>` |\n| \u02A6 `_pathlessLayout.route-b.tsx` | `/route-b` | `<Root><PathlessLayout><RouteB>` |\n| \u02A6 `files.$.tsx` | `/files/$` | `<Root><Files>` |\n| \u02A6 `account.tsx` | `/account` | `<Root><Account>` |\n| \u02A6 `account.overview.tsx` | `/account/overview` | `<Root><Account><Overview>` |\n\n## Mixed Flat and Directory Routes\n\nIt'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:\n\nSee the example below:\n\n| Filename | Route Path | Component Output |\n| ------------------------------ | ------------------------- | --------------------------------- |\n| \u02A6 `__root.tsx` | | `<Root>` |\n| \u02A6 `index.tsx` | `/` (exact) | `<Root><RootIndex>` |\n| \u02A6 `about.tsx` | `/about` | `<Root><About>` |\n| \u02A6 `posts.tsx` | `/posts` | `<Root><Posts>` |\n| \uD83D\uDCC2 `posts` | | |\n| \u2504 \u02A6 `index.tsx` | `/posts` (exact) | `<Root><Posts><PostsIndex>` |\n| \u2504 \u02A6 `$postId.tsx` | `/posts/$postId` | `<Root><Posts><Post>` |\n| \u2504 \u02A6 `$postId.edit.tsx` | `/posts/$postId/edit` | `<Root><Posts><Post><EditPost>` |\n| \u02A6 `settings.tsx` | `/settings` | `<Root><Settings>` |\n| \u02A6 `settings.profile.tsx` | `/settings/profile` | `<Root><Settings><Profile>` |\n| \u02A6 `settings.notifications.tsx` | `/settings/notifications` | `<Root><Settings><Notifications>` |\n| \u02A6 `account.tsx` | `/account` | `<Root><Account>` |\n| \u02A6 `account.overview.tsx` | `/account/overview` | `<Root><Account><Overview>` |\n\nBoth flat and directory routes can be mixed together to create a route tree that uses the best of both worlds where it makes sense.\n\n> [!TIP]\n> If you find that the default file-based routing structure doesn't fit your needs, you can always use [Virtual File Routes](../virtual-file-routes.md) to control the source of your routes whilst still getting the awesome performance benefits of file-based routing.\n\n## Getting started with File-Based Routing\n\nTo 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.\n\nTo enable file-based routing, you'll need to be using React with a supported bundler. See if your bundler is listed in the configuration guides below.\n\n[//]: # 'SupportedBundlersList'\n\n- [Installation with Vite](../installation-with-vite.md)\n- [Installation with Rspack/Rsbuild](../installation-with-rspack.md)\n- [Installation with Webpack](../installation-with-webpack.md)\n- [Installation with Esbuild](../installation-with-esbuild.md)\n\n[//]: # 'SupportedBundlersList'\n\nWhen 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.\n\nIf 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`](../installation-with-router-cli.md) package to generate your route tree file.\n\n# File Naming Conventions\n\nFile-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](../route-trees.md) guide.\n\n| Feature | Description |\n| ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **`__root.tsx`** | The root route file must be named `__root.tsx` and must be placed in the root of the configured `routesDirectory`. |\n| **`.` Separator** | Routes can use the `.` character to denote a nested route. For example, `blog.post` will be generated as a child of `blog`. |\n| **`$` Token** | Route segments with the `$` token are parameterized and will extract the value from the URL pathname as a route `param`. |\n| **`_` Prefix** | Route segments with the `_` prefix are considered to be pathless layout routes and will not be used when matching its child routes against the URL pathname. |\n| **`_` Suffix** | Route segments with the `_` suffix exclude the route from being nested under any parent routes. |\n| **`-` Prefix** | Files and folders with the `-` prefix are excluded from the route tree. They will not be added to the `routeTree.gen.ts` file and can be used to colocate logic in route folders. |\n| **`(folder)` folder name pattern** | A folder that matches this pattern is treated as a **route group**, preventing the folder from being included in the route's URL path. |\n| **`index` Token** | Route segments ending with the `index` token (before any file extensions) will match the parent route when the URL pathname matches the parent route exactly. This can be configured via the `indexToken` configuration option, see [options](../../../../api/file-based-routing.md#indextoken). |\n| **`.route.tsx` File Type** | When using directories to organise routes, the `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 as the route file for the `/blog/post` route. This can be configured via the `routeToken` configuration option, see [options](../../../../api/file-based-routing.md#routetoken). |\n\n> **\uD83D\uDCA1 Remember:** The file-naming conventions for your project could be affected by what [options](../../../../api/file-based-routing.md) are configured.\n\n## Dynamic Path Params\n\nDynamic 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:\n\n| Filename | Route Path | Component Output |\n| --------------------- | ---------------- | --------------------- |\n| ... | ... | ... |\n| \u02A6 `posts.$postId.tsx` | `/posts/$postId` | `<Root><Posts><Post>` |\n\nWe'll learn more about dynamic path params in the [Path Params](../../guide/path-params.md) guide.\n\n## Pathless Routes\n\nPathless 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:\n\n| Filename | Route Path | Component Output |\n| -------------- | ---------- | ---------------- |\n| \u02A6 `_app.tsx` | | |\n| \u02A6 `_app.a.tsx` | /a | `<Root><App><A>` |\n| \u02A6 `_app.b.tsx` | /b | `<Root><App><B>` |\n\nTo learn more about pathless routes, see the [Routing Concepts - Pathless Routes](../routing-concepts.md#pathless-layout-routes) guide.\n\n# Installation with Vite\n\n[//]: # 'BundlerConfiguration'\n\nTo use file-based routing with **Esbuild**, you'll need to install the `@tanstack/router-plugin` package.\n\n```sh\nnpm install -D @tanstack/router-plugin\n```\n\nOnce installed, you'll need to add the plugin to your configuration.\n\n```tsx\n// esbuild.config.js\nimport { tanstackRouter } from '@tanstack/router-plugin/esbuild'\n\nexport default {\n // ...\n plugins: [\n tanstackRouter({\n target: 'react',\n autoCodeSplitting: true,\n }),\n ],\n}\n```\n\nOr, you can clone our [Quickstart Esbuild example](https://github.com/TanStack/router/tree/main/examples/react/quickstart-esbuild-file-based) and get started.\n\nNow that you've added the plugin to your Esbuild configuration, you're all set to start using file-based routing with TanStack Router.\n\n[//]: # 'BundlerConfiguration'\n\n## Ignoring the generated route tree file\n\nIf 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.\n\nHere are some resources to help you ignore the generated route tree file:\n\n- Prettier - [https://prettier.io/docs/en/ignore.html#ignoring-files-prettierignore](https://prettier.io/docs/en/ignore.html#ignoring-files-prettierignore)\n- ESLint - [https://eslint.org/docs/latest/use/configure/ignore#ignoring-files](https://eslint.org/docs/latest/use/configure/ignore#ignoring-files)\n- Biome - [https://biomejs.dev/reference/configuration/#filesignore](https://biomejs.dev/reference/configuration/#filesignore)\n\n> [!WARNING]\n> If you are using VSCode, you may experience the route tree file unexpectedly open (with errors) after renaming a route.\n\nYou can prevent that from the VSCode settings by marking the file as readonly. Our recommendation is to also exclude it from search results and file watcher with the following settings:\n\n```json\n{\n \"files.readonlyInclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"files.watcherExclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"search.exclude\": {\n \"**/routeTree.gen.ts\": true\n }\n}\n```\n\nYou can use those settings either at a user level or only for a single workspace by creating the file `.vscode/settings.json` at the root of your project.\n\n## Configuration\n\nWhen using the TanStack Router Plugin with Esbuild for File-based routing, it comes with some sane defaults that should work for most projects:\n\n```json\n{\n \"routesDirectory\": \"./src/routes\",\n \"generatedRouteTree\": \"./src/routeTree.gen.ts\",\n \"routeFileIgnorePrefix\": \"-\",\n \"quoteStyle\": \"single\"\n}\n```\n\nIf 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 editing the configuration object passed into the `tanstackRouter` function.\n\nYou can find all the available configuration options in the [File-based Routing API Reference](../../../../api/file-based-routing.md).\n\n# Installation with Router CLI\n\n> [!WARNING]\n> You should only use the TanStack Router CLI if you are not using a supported bundler. The CLI only supports the generation of the route tree file and does not provide any other features.\n\nTo use file-based routing with the TanStack Router CLI, you'll need to install the `@tanstack/router-cli` package.\n\n```sh\nnpm install -D @tanstack/router-cli\n```\n\nOnce installed, you'll need to amend your your scripts in your `package.json` for the CLI to `watch` and `generate` files.\n\n```json\n{\n \"scripts\": {\n \"generate-routes\": \"tsr generate\",\n \"watch-routes\": \"tsr watch\",\n \"build\": \"npm run generate-routes && ...\",\n \"dev\": \"npm run watch-routes && ...\"\n }\n}\n```\n\n[//]: # 'AfterScripts'\n[//]: # 'AfterScripts'\n\nYou shouldn't forget to _ignore_ the generated route tree file. Head over to the [Ignoring the generated route tree file](#ignoring-the-generated-route-tree-file) section to learn more.\n\nWith the CLI installed, the following commands are made available via the `tsr` command\n\n## Using the `generate` command\n\nGenerates the routes for a project based on the provided configuration.\n\n```sh\ntsr generate\n```\n\n## Using the `watch` command\n\nContinuously watches the specified directories and regenerates routes as needed.\n\n**Usage:**\n\n```sh\ntsr watch\n```\n\nWith 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.\n\n## Ignoring the generated route tree file\n\nIf 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.\n\nHere are some resources to help you ignore the generated route tree file:\n\n- Prettier - [https://prettier.io/docs/en/ignore.html#ignoring-files-prettierignore](https://prettier.io/docs/en/ignore.html#ignoring-files-prettierignore)\n- ESLint - [https://eslint.org/docs/latest/use/configure/ignore#ignoring-files](https://eslint.org/docs/latest/use/configure/ignore#ignoring-files)\n- Biome - [https://biomejs.dev/reference/configuration/#filesignore](https://biomejs.dev/reference/configuration/#filesignore)\n\n> [!WARNING]\n> If you are using VSCode, you may experience the route tree file unexpectedly open (with errors) after renaming a route.\n\nYou can prevent that from the VSCode settings by marking the file as readonly. Our recommendation is to also exclude it from search results and file watcher with the following settings:\n\n```json\n{\n \"files.readonlyInclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"files.watcherExclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"search.exclude\": {\n \"**/routeTree.gen.ts\": true\n }\n}\n```\n\nYou can use those settings either at a user level or only for a single workspace by creating the file `.vscode/settings.json` at the root of your project.\n\n## Configuration\n\nWhen using the TanStack Router CLI for File-based routing, it comes with some sane defaults that should work for most projects:\n\n```json\n{\n \"routesDirectory\": \"./src/routes\",\n \"generatedRouteTree\": \"./src/routeTree.gen.ts\",\n \"routeFileIgnorePrefix\": \"-\",\n \"quoteStyle\": \"single\"\n}\n```\n\nIf 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.\n\n[//]: # 'TargetConfiguration'\n[//]: # 'TargetConfiguration'\n\nYou can find all the available configuration options in the [File-based Routing API Reference](../../../../api/file-based-routing.md).\n\n# Installation with Rspack\n\n[//]: # 'BundlerConfiguration'\n\nTo use file-based routing with **Rspack** or **Rsbuild**, you'll need to install the `@tanstack/router-plugin` package.\n\n```sh\nnpm install -D @tanstack/router-plugin\n```\n\nOnce installed, you'll need to add the plugin to your configuration.\n\n```tsx\n// rsbuild.config.ts\nimport { defineConfig } from '@rsbuild/core'\nimport { pluginReact } from '@rsbuild/plugin-react'\nimport { tanstackRouter } from '@tanstack/router-plugin/rspack'\n\nexport default defineConfig({\n plugins: [pluginReact()],\n tools: {\n rspack: {\n plugins: [\n tanstackRouter({\n target: 'react',\n autoCodeSplitting: true,\n }),\n ],\n },\n },\n})\n```\n\nOr, you can clone our [Quickstart Rspack/Rsbuild example](https://github.com/TanStack/router/tree/main/examples/react/quickstart-rspack-file-based) and get started.\n\nNow that you've added the plugin to your Rspack/Rsbuild configuration, you're all set to start using file-based routing with TanStack Router.\n\n[//]: # 'BundlerConfiguration'\n\n## Ignoring the generated route tree file\n\nIf 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.\n\nHere are some resources to help you ignore the generated route tree file:\n\n- Prettier - [https://prettier.io/docs/en/ignore.html#ignoring-files-prettierignore](https://prettier.io/docs/en/ignore.html#ignoring-files-prettierignore)\n- ESLint - [https://eslint.org/docs/latest/use/configure/ignore#ignoring-files](https://eslint.org/docs/latest/use/configure/ignore#ignoring-files)\n- Biome - [https://biomejs.dev/reference/configuration/#filesignore](https://biomejs.dev/reference/configuration/#filesignore)\n\n> [!WARNING]\n> If you are using VSCode, you may experience the route tree file unexpectedly open (with errors) after renaming a route.\n\nYou can prevent that from the VSCode settings by marking the file as readonly. Our recommendation is to also exclude it from search results and file watcher with the following settings:\n\n```json\n{\n \"files.readonlyInclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"files.watcherExclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"search.exclude\": {\n \"**/routeTree.gen.ts\": true\n }\n}\n```\n\nYou can use those settings either at a user level or only for a single workspace by creating the file `.vscode/settings.json` at the root of your project.\n\n## Configuration\n\nWhen using the TanStack Router Plugin with Rspack (or Rsbuild) for File-based routing, it comes with some sane defaults that should work for most projects:\n\n```json\n{\n \"routesDirectory\": \"./src/routes\",\n \"generatedRouteTree\": \"./src/routeTree.gen.ts\",\n \"routeFileIgnorePrefix\": \"-\",\n \"quoteStyle\": \"single\"\n}\n```\n\nIf 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 editing the configuration object passed into the `tanstackRouter` function.\n\nYou can find all the available configuration options in the [File-based Routing API Reference](../../../../api/file-based-routing.md).\n\n# Installation with Vite\n\n[//]: # 'BundlerConfiguration'\n\nTo use file-based routing with **Vite**, you'll need to install the `@tanstack/router-plugin` package.\n\n```sh\nnpm install -D @tanstack/router-plugin\n```\n\nOnce installed, you'll need to add the plugin to your Vite configuration.\n\n```ts\n// vite.config.ts\nimport { defineConfig } from 'vite'\nimport react from '@vitejs/plugin-react'\nimport { tanstackRouter } from '@tanstack/router-plugin/vite'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n plugins: [\n // Please make sure that '@tanstack/router-plugin' is passed before '@vitejs/plugin-react'\n tanstackRouter({\n target: 'react',\n autoCodeSplitting: true,\n }),\n react(),\n // ...\n ],\n})\n```\n\nOr, you can clone our [Quickstart Vite example](https://github.com/TanStack/router/tree/main/examples/react/quickstart-file-based) and get started.\n\n> [!WARNING]\n> 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.\n\nNow that you've added the plugin to your Vite configuration, you're all set to start using file-based routing with TanStack Router.\n\n[//]: # 'BundlerConfiguration'\n\n## Ignoring the generated route tree file\n\nIf 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.\n\nHere are some resources to help you ignore the generated route tree file:\n\n- Prettier - [https://prettier.io/docs/en/ignore.html#ignoring-files-prettierignore](https://prettier.io/docs/en/ignore.html#ignoring-files-prettierignore)\n- ESLint - [https://eslint.org/docs/latest/use/configure/ignore#ignoring-files](https://eslint.org/docs/latest/use/configure/ignore#ignoring-files)\n- Biome - [https://biomejs.dev/reference/configuration/#filesignore](https://biomejs.dev/reference/configuration/#filesignore)\n\n> [!WARNING]\n> If you are using VSCode, you may experience the route tree file unexpectedly open (with errors) after renaming a route.\n\nYou can prevent that from the VSCode settings by marking the file as readonly. Our recommendation is to also exclude it from search results and file watcher with the following settings:\n\n```json\n{\n \"files.readonlyInclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"files.watcherExclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"search.exclude\": {\n \"**/routeTree.gen.ts\": true\n }\n}\n```\n\nYou can use those settings either at a user level or only for a single workspace by creating the file `.vscode/settings.json` at the root of your project.\n\n## Configuration\n\nWhen using the TanStack Router Plugin with Vite for File-based routing, it comes with some sane defaults that should work for most projects:\n\n```json\n{\n \"routesDirectory\": \"./src/routes\",\n \"generatedRouteTree\": \"./src/routeTree.gen.ts\",\n \"routeFileIgnorePrefix\": \"-\",\n \"quoteStyle\": \"single\"\n}\n```\n\nIf 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 editing the configuration object passed into the `tanstackRouter` function.\n\nYou can find all the available configuration options in the [File-based Routing API Reference](../../../../api/file-based-routing.md).\n\n# Installation with Webpack\n\n[//]: # 'BundlerConfiguration'\n\nTo use file-based routing with **Webpack**, you'll need to install the `@tanstack/router-plugin` package.\n\n```sh\nnpm install -D @tanstack/router-plugin\n```\n\nOnce installed, you'll need to add the plugin to your configuration.\n\n```tsx\n// webpack.config.ts\nimport { tanstackRouter } from '@tanstack/router-plugin/webpack'\n\nexport default {\n plugins: [\n tanstackRouter({\n target: 'react',\n autoCodeSplitting: true,\n }),\n ],\n}\n```\n\nOr, you can clone our [Quickstart Webpack example](https://github.com/TanStack/router/tree/main/examples/react/quickstart-webpack-file-based) and get started.\n\nNow that you've added the plugin to your Webpack configuration, you're all set to start using file-based routing with TanStack Router.\n\n[//]: # 'BundlerConfiguration'\n\n## Ignoring the generated route tree file\n\nIf 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.\n\nHere are some resources to help you ignore the generated route tree file:\n\n- Prettier - [https://prettier.io/docs/en/ignore.html#ignoring-files-prettierignore](https://prettier.io/docs/en/ignore.html#ignoring-files-prettierignore)\n- ESLint - [https://eslint.org/docs/latest/use/configure/ignore#ignoring-files](https://eslint.org/docs/latest/use/configure/ignore#ignoring-files)\n- Biome - [https://biomejs.dev/reference/configuration/#filesignore](https://biomejs.dev/reference/configuration/#filesignore)\n\n> [!WARNING]\n> If you are using VSCode, you may experience the route tree file unexpectedly open (with errors) after renaming a route.\n\nYou can prevent that from the VSCode settings by marking the file as readonly. Our recommendation is to also exclude it from search results and file watcher with the following settings:\n\n```json\n{\n \"files.readonlyInclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"files.watcherExclude\": {\n \"**/routeTree.gen.ts\": true\n },\n \"search.exclude\": {\n \"**/routeTree.gen.ts\": true\n }\n}\n```\n\nYou can use those settings either at a user level or only for a single workspace by creating the file `.vscode/settings.json` at the root of your project.\n\n## Configuration\n\nWhen using the TanStack Router Plugin with Webpack for File-based routing, it comes with some sane defaults that should work for most projects:\n\n```json\n{\n \"routesDirectory\": \"./src/routes\",\n \"generatedRouteTree\": \"./src/routeTree.gen.ts\",\n \"routeFileIgnorePrefix\": \"-\",\n \"quoteStyle\": \"single\"\n}\n```\n\nIf 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 editing the configuration object passed into the `tanstackRouter` function.\n\nYou can find all the available configuration options in the [File-based Routing API Reference](../../../../api/file-based-routing.md).\n\n# Route Matching\n\nRoute matching follows a consistent and predictable pattern. This guide will explain how route trees are matched.\n\nWhen TanStack Router processes your route tree, all of your routes are automatically sorted to match the most specific routes first. This means that regardless of the order your route tree is defined, routes will always be sorted in this order:\n\n- Index Route\n- Static Routes (most specific to least specific)\n- Dynamic Routes (longest to shortest)\n- Splat/Wildcard Routes\n\nConsider the following pseudo route tree:\n\n```\nRoot\n - blog\n - $postId\n - /\n - new\n - /\n - *\n - about\n - about/us\n```\n\nAfter sorting, this route tree will become:\n\n```\nRoot\n - /\n - about/us\n - about\n - blog\n - /\n - new\n - $postId\n - *\n```\n\nThis final order represents the order in which routes will be matched based on specificity.\n\nUsing that route tree, let's follow the matching process for a few different URLs:\n\n- `/blog`\n ```\n Root\n \u274C /\n \u274C about/us\n \u274C about\n \u23E9 blog\n \u2705 /\n - new\n - $postId\n - *\n ```\n- `/blog/my-post`\n ```\n Root\n \u274C /\n \u274C about/us\n \u274C about\n \u23E9 blog\n \u274C /\n \u274C new\n \u2705 $postId\n - *\n ```\n- `/`\n ```\n Root\n \u2705 /\n - about/us\n - about\n - blog\n - /\n - new\n - $postId\n - *\n ```\n- `/not-a-route`\n ```\n Root\n \u274C /\n \u274C about/us\n \u274C about\n \u274C blog\n - /\n - new\n - $postId\n \u2705 *\n ```\n\n# Route Trees\n\nTanStack Router uses a nested route tree to match up the URL with the correct component tree to render.\n\nTo build a route tree, TanStack Router supports:\n\n- [File-Based Routing](../file-based-routing.md)\n- [Code-Based Routing](../code-based-routing.md)\n\nBoth methods support the exact same core features and functionality, but **file-based routing requires less code for the same or better results**. For this reason, **file-based routing is the preferred and recommended way** to configure TanStack Router. Most of the documentation is written from the perspective of file-based routing.\n\n## Route Trees\n\nNested routing is a powerful concept that allows you to use a URL to render a nested component tree. For example, given the URL of `/blog/posts/123`, you could create a route hierarchy that looks like this:\n\n```tsx\n\u251C\u2500\u2500 blog\n\u2502 \u251C\u2500\u2500 posts\n\u2502 \u2502 \u251C\u2500\u2500 $postId\n```\n\nAnd render a component tree that looks like this:\n\n```tsx\n<Blog>\n <Posts>\n <Post postId=\"123\" />\n </Posts>\n</Blog>\n```\n\nLet's take that concept and expand it out to a larger site structure, but with