Skip to main content

File-Based Routing

TanStack Router supports file-based routing, which automatically generates your route tree from your file system structure. This approach provides excellent developer experience with type safety and automatic route generation.

Overview

File-based routing eliminates the need to manually define routes by deriving them from your file structure. The router automatically generates type-safe routes based on your file naming conventions.

Setup

1

Install the Router Plugin

Install the TanStack Router plugin for your bundler:
npm install -D @tanstack/router-plugin
2

Configure Your Bundler

Add the plugin to your bundler configuration:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { TanStackRouterPlugin } from '@tanstack/router-plugin/vite'

export default defineConfig({
  plugins: [
    TanStackRouterPlugin(),
    react(),
  ],
})
3

Create Your Routes Directory

Create a src/routes/ directory for your route files:
mkdir src/routes
4

Create the Root Route

Every file-based router needs a root route. Create src/routes/__root.tsx:
src/routes/__root.tsx
import { Link, Outlet, createRootRoute } from '@tanstack/react-router'
import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'

export const Route = createRootRoute({
  component: RootComponent,
})

function RootComponent() {
  return (
    <>
      <div className="p-2 flex gap-2">
        <Link to="/" className="[&.active]:font-bold">
          Home
        </Link>
        <Link to="/about" className="[&.active]:font-bold">
          About
        </Link>
      </div>
      <hr />
      <Outlet />
      <TanStackRouterDevtools />
    </>
  )
}
5

Create Route Files

Create route files following the naming conventions:
src/routes/index.tsx
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/')({')
  component: IndexComponent,
})

function IndexComponent() {
  return <div>Welcome Home!</div>
}
6

Import and Use the Generated Route Tree

The plugin automatically generates a routeTree.gen.ts file. Import it in your main file:
src/main.tsx
import { RouterProvider, createRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen'

const router = createRouter({ routeTree })

declare module '@tanstack/react-router' {
  interface Register {
    router: typeof router
  }
}

function App() {
  return <RouterProvider router={router} />
}

File Naming Conventions

Index Routes

Files named index.tsx create index routes:
src/routes/index.tsx → /
src/routes/posts/index.tsx → /posts

Dynamic Route Segments

Use $ prefix for dynamic parameters:
src/routes/posts/$postId.tsx → /posts/:postId
src/routes/users/$userId/profile.tsx → /users/:userId/profile
src/routes/posts/$postId.tsx
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/posts/$postId')({
  loader: async ({ params }) => {
    return fetchPost(params.postId)
  },
  component: PostComponent,
})

function PostComponent() {
  const post = Route.useLoaderData()
  return <div>{post.title}</div>
}

Layout Routes

Files ending in .route.tsx or without a component create layouts:
src/routes/posts.route.tsx
import { createFileRoute, Outlet } from '@tanstack/react-router'

export const Route = createFileRoute('/posts')({
  component: PostsLayout,
})

function PostsLayout() {
  return (
    <div>
      <h1>Posts</h1>
      <Outlet />
    </div>
  )
}

Pathless Layouts

Use _ prefix for routes that don’t add a path segment:
src/routes/_layout.tsx → (no path)
src/routes/_layout/dashboard.tsx → /dashboard
src/routes/_layout/settings.tsx → /settings
src/routes/_layout.tsx
import { createFileRoute, Outlet } from '@tanstack/react-router'

export const Route = createFileRoute('/_layout')({
  component: LayoutComponent,
})

function LayoutComponent() {
  return (
    <div className="layout">
      <Outlet />
    </div>
  )
}

Splat/Catch-All Routes

Use $.tsx for catch-all routes:
src/routes/files/$.tsx → /files/*

Route Configuration

File-based routes support all the same options as code-based routes:
src/routes/posts/$postId.tsx
import { createFileRoute } from '@tanstack/react-router'
import { ErrorComponent } from '@tanstack/react-router'

export const Route = createFileRoute('/posts/$postId')({
  // Data loading
  loader: async ({ params }) => fetchPost(params.postId),
  
  // Before navigation guard
  beforeLoad: ({ context }) => {
    if (!context.user) {
      throw redirect({ to: '/login' })
    }
  },
  
  // Error handling
  errorComponent: ({ error }) => <ErrorComponent error={error} />,
  
  // Not found handling
  notFoundComponent: () => <div>Post not found</div>,
  
  // Pending component while loading
  pendingComponent: () => <div>Loading post...</div>,
  
  // Component to render
  component: PostComponent,
})

function PostComponent() {
  const post = Route.useLoaderData()
  return <div>{post.title}</div>
}

Plugin Configuration

Customize the plugin behavior:
vite.config.ts
import { TanStackRouterPlugin } from '@tanstack/router-plugin/vite'

export default {
  plugins: [
    TanStackRouterPlugin({
      // Routes directory (default: './src/routes')
      routesDirectory: './src/routes',
      
      // Generated route tree file (default: './src/routeTree.gen.ts')
      generatedRouteTree: './src/routeTree.gen.ts',
      
      // Auto-generate route tree on file changes (default: true)
      autoCodeSplitting: true,
    }),
  ],
}

Benefits of File-Based Routing

Type Safety

Automatic type generation for all routes, params, and search params

Developer Experience

No manual route configuration - just create files and they work

Code Splitting

Automatic code splitting based on your file structure

Conventions

Clear, standard conventions for organizing your routes

Best Practices

Co-locate related files: Keep components, hooks, and utilities close to the routes that use them.
Avoid conflicts: Don’t create routes with overlapping paths. File-based routing will detect and warn about conflicts.
src/routes/
  __root.tsx
  index.tsx
  posts/
    index.tsx
    $postId.tsx
    components/
      PostCard.tsx
    utils/
      fetchPost.ts

Next Steps

Nested Routes

Learn how to create nested route hierarchies

Route Guards

Protect routes with authentication and authorization

Build docs developers (and LLMs) love