TanStack Router 01 ⚛️ Installation — Setup & dependencies
TanStack Router is a type-safe routing library for React and Solid. Unlike React Router, which relies on runtime matching, TanStack Router generates a fully typed route tree that the TypeScript compiler can verify. The installation process is split into two paths: the CLI scaffold for new projects, and the manual setup for existing projects. The critical detail is that the file-based routing approach requires the @tanstack/router-plugin dev dependency to generate the route tree, while the code-based approach does not. The plugin must be configured before the React plugin in the Vite configuration, or the route generation fails silently.
Key point: The core package is @tanstack/react-router. The file-based routing requires @tanstack/router-plugin as a dev dependency. The plugin must appear before @vitejs/plugin-react in the Vite plugins array. The generated route tree lives at src/routeTree.gen.ts and should be ignored by the linter and formatter.
Why installation requires a specific mental model
The file-based versus code-based problem. TanStack Router supports two routing paradigms. The file-based approach uses the filesystem under src/routes/ as the route definition. Each file exports a Route object created by createFileRoute. The plugin watches this directory and generates the routeTree.gen.ts file, which the router imports. The code-based approach defines the routes programmatically with createRoute and createRootRoute. The code-based approach does not need the plugin, but it loses the automatic code splitting and the file-system conventions .
The plugin ordering problem. The Vite configuration must place tanstackRouter() before react(). The plugin transforms the route files and generates the route tree. If the React plugin runs first, the transformed code may not include the route tree imports, and the application fails to compile. The documentation explicitly states: “Please make sure that ‘@tanstack/router-plugin’ is passed before ‘@vitejs/plugin-react'” .
The generated file problem. The routeTree.gen.ts file is generated by the plugin. It should not be edited manually. It should be ignored by the linter and the formatter, and the editor should mark it as readonly to prevent accidental edits. The file is regenerated on every npm run dev and npm run build when the plugin is active .
The TypeScript requirement problem. TanStack Router is built around type safety. The strict mode is recommended in tsconfig.json. The moduleResolution should be bundler, and the jsx should be react-jsx for React. The router’s type-safe navigation depends on the generated route tree and the TypeScript compiler .
The trade-off. The CLI scaffold is the fastest path for a new project. It creates the directory structure, the Vite configuration, and the initial routes. The manual setup is the correct path for an existing project that already has a Vite configuration and a specific directory structure. The manual setup requires more steps but gives full control over the file organization and the plugin options.
a. Scaffolding a new project with the CLI
The fastest way to start is the @tanstack/cli with the --router-only flag. The CLI prompts for the file-based or code-based approach, the TypeScript support, the Tailwind integration, and the Git initialization .
# Scaffold a new project
npx @tanstack/cli create --router-only
# Or with a specific name
npx @tanstack/cli create my-app --router-only
The CLI generates the project with the dependencies installed and the Vite configuration set up. The npm run dev command starts the development server on the default Vite port .
For a React project without the full CLI, the create-tsrouter-app is the alternative.
# Create a React project with TanStack Router
npx create-tsrouter-app@latest my-app
The CLI creates the src/routes/ directory, the __root.tsx file, the index.tsx file, and the main.tsx file. The routeTree.gen.ts is generated on the first npm run dev .
b. Manual setup for an existing project
The manual setup installs the core package and, for file-based routing, the plugin. The Vite configuration must include the plugin.
# Core dependencies
npm i @tanstack/react-router @tanstack/react-router-devtools
# Dev dependency for file-based routing
npm i -D @tanstack/router-plugin
The vite.config.ts must import the plugin and place it before the React plugin.
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { tanstackRouter } from '@tanstack/router-plugin/vite'
export default defineConfig({
plugins: [
tanstackRouter({
target: 'react',
autoCodeSplitting: true,
}),
react(),
],
})
The target: 'react' tells the plugin to generate the route tree for React. The autoCodeSplitting: true enables automatic code splitting for the routes. The plugin generates the src/routeTree.gen.ts file on the first run .
The src/main.tsx must import the generated route tree and create the router.
import { StrictMode } from 'react'
import ReactDOM from 'react-dom/client'
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
}
}
const rootElement = document.getElementById('root')!
if (!rootElement.innerHTML) {
const root = ReactDOM.createRoot(rootElement)
root.render(
<StrictMode>
<RouterProvider router={router} />
</StrictMode>
)
}
The declare module block registers the router type for the type-safe navigation. Without it, the Link and useNavigate hooks do not have the route path types .
c. The route files for file-based routing
The file-based routing uses the src/routes/ directory. The __root.tsx is the root layout, and the index.tsx is the home route.
// src/routes/__root.tsx
import { createRootRoute, Link, Outlet } from '@tanstack/react-router'
import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'
export const Route = createRootRoute({
component: RootLayout,
})
function RootLayout() {
return (
<>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
<Outlet />
<TanStackRouterDevtools />
</>
)
}
The createRootRoute defines the root layout. The <Outlet /> is the placeholder for the child routes. The <Link> is the navigation component. The <TanStackRouterDevtools /> is the optional devtools panel .
// src/routes/index.tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/')({
component: Index,
})
function Index() {
return <div>Hello from Home!</div>
}
The createFileRoute('/') creates the route for the root path. The path is the string that matches the file’s location in the routes directory. The component is the React component that renders when the path matches .
// src/routes/about.tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/about')({
component: About,
})
function About() {
return <div>Hello from About!</div>
}
The /about path matches the about.tsx file. The plugin generates the route tree that connects the file to the path .
Complete Example Session
# ============================================
# PART 1: INSTALL DEPENDENCIES
# ============================================
npm i @tanstack/react-router @tanstack/react-router-devtools
npm i -D @tanstack/router-plugin
# ============================================
# PART 2: CONFIGURE VITE
# ============================================
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { tanstackRouter } from '@tanstack/router-plugin/vite'
export default defineConfig({
plugins: [
tanstackRouter({ target: 'react', autoCodeSplitting: true }),
react(),
],
})
# ============================================
# PART 3: CREATE THE ROOT ROUTE
# ============================================
// src/routes/__root.tsx
import { createRootRoute, Link, Outlet } from '@tanstack/react-router'
export const Route = createRootRoute({ component: RootLayout })
function RootLayout() {
return (
<>
<nav><Link to="/">Home</Link></nav>
<Outlet />
</>
)
}
# ============================================
# PART 4: CREATE THE INDEX ROUTE
# ============================================
// src/routes/index.tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/')({ component: Index })
function Index() {
return <div>Home</div>
}
# ============================================
# PART 5: CREATE THE ABOUT ROUTE
# ============================================
// src/routes/about.tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/about')({ component: About })
function About() {
return <div>About</div>
}
# ============================================
# PART 6: UPDATE MAIN.TSX
# ============================================
// src/main.tsx
import { StrictMode } from 'react'
import ReactDOM from 'react-dom/client'
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 }
}
const root = ReactDOM.createRoot(document.getElementById('root')!)
root.render(
<StrictMode>
<RouterProvider router={router} />
</StrictMode>
)
# ============================================
# PART 7: IGNORE THE GENERATED FILE
# ============================================
# .prettierignore
routeTree.gen.ts
# .eslintignore
routeTree.gen.ts
# ============================================
# PART 8: START THE DEV SERVER
# ============================================
npm run dev
# The plugin generates routeTree.gen.ts
# The server starts on http://localhost:5173
# ============================================
# PART 9: VERIFY THE ROUTES
# ============================================
# / → Index component
# /about → About component
# The routeTree.gen.ts has the route definitions.
The nine parts trace the installation: dependencies, Vite configuration, root route, index route, about route, main entry, ignore file, dev server, and verification.
Quick Reference
Core Dependencies
| Package | Purpose |
|---|---|
@tanstack/react-router | Router core |
@tanstack/react-router-devtools | Devtools (optional) |
File-Based Dev Dependency
| Package | Purpose |
|---|---|
@tanstack/router-plugin | Route tree generation |
Vite Configuration
| Setting | Value |
|---|---|
| Plugin order | tanstackRouter() before react() |
target | 'react' |
autoCodeSplitting | true |
Route Files
| File | Purpose |
|---|---|
src/routes/__root.tsx | Root layout |
src/routes/index.tsx | Home route |
src/routes/about.tsx | About route |
Generated File
| File | Purpose |
|---|---|
src/routeTree.gen.ts | Route tree (generated) |
Minimum Versions
| Dependency | Version |
|---|---|
| React | 18 or later |
| React DOM | 18 or later |
| TypeScript | 5.3 or later |
Best Practices
✅ Do This:
tanstackRouter({ target: 'react' }), react()
<!-- Place the router plugin before React --> # ✅
import { routeTree } from './routeTree.gen'
<!-- Import the generated tree --> # ✅
routeTree.gen.ts
<!-- Ignore the generated file in linter --> # ✅
❌ Don’t Do This:
react(), tanstackRouter()
<!-- Wrong plugin order breaks generation --> # ❌
# Edit routeTree.gen.ts manually
<!-- The plugin overwrites it --> # ❌
# Use file-based routing without the plugin
<!-- The route tree is not generated --> # ❌
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| Route tree not generated | Plugin not configured | Add tanstackRouter() to Vite |
| Plugin error | Wrong order | Place before react() |
Type errors on Link | Missing declare module | Add the router registration |
| Route not matching | Wrong file path | Check the filename matches the path |
| Linter errors on generated file | Not ignored | Add to .prettierignore and .eslintignore |
Real-World Examples
1. Install Core
npm i @tanstack/react-router
2. Install Plugin
npm i -D @tanstack/router-plugin
3. Vite Config
plugins: [tanstackRouter({ target: 'react' }), react()]
4. Root Route
export const Route = createRootRoute({ component: RootLayout })
5. Index Route
export const Route = createFileRoute('/')({ component: Index })
6. Router Instance
const router = createRouter({ routeTree })
7. Type Registration
declare module '@tanstack/react-router' { interface Register { router: typeof router } }
8. Render
<RouterProvider router={router} />
9. Ignore Generated
routeTree.gen.ts
10. Start Dev
npm run dev
Visual
Installation Flow
┌──────────────────────────────────────────────┐
│ Install dependencies │
│ ├── @tanstack/react-router │
│ └── @tanstack/router-plugin (file-based) │
└──────────────────┬───────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ Configure Vite │
│ ├── tanstackRouter() before react() │
│ └── target: 'react' │
└──────────────────┬───────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ Create route files │
│ ├── __root.tsx │
│ ├── index.tsx │
│ └── about.tsx │
└──────────────────┬───────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ Start dev server │
│ → routeTree.gen.ts generated │
└──────────────────────────────────────────────┘
Plugin Order
┌──────────────────────────────────────────────┐
│ plugins: [ │
│ tanstackRouter({ target: 'react' }), │
│ react(), │
│ ] │
└──────────────────┬───────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ Router plugin runs first │
│ → Transforms route files │
│ → Generates routeTree.gen.ts │
└──────────────────────────────────────────────┘
Summary
| Item | Value |
|---|---|
| Core package | @tanstack/react-router |
| Devtools package | @tanstack/react-router-devtools |
| File-based dev dependency | @tanstack/router-plugin |
| Vite plugin import | @tanstack/router-plugin/vite |
| Plugin order | Before @vitejs/plugin-react |
| Root route file | src/routes/__root.tsx |
| Generated file | src/routeTree.gen.ts |
| Minimum React | 18 |
| Minimum TypeScript | 5.3 |
Key takeaways:
- The core package is
@tanstack/react-router. The devtools package is optional. The@tanstack/router-pluginis the dev dependency for file-based routing . - The plugin must run before the React plugin. The
tanstackRouter()call in the Vitepluginsarray must appear beforereact(). The wrong order breaks the route tree generation . - The generated route tree is the connection. The
src/routeTree.gen.tsfile is generated by the plugin. Themain.tsximports it and passes it tocreateRouter. The file should be ignored by the linter and formatter . - The type registration is required for type-safe navigation. The
declare moduleblock registers the router type. Without it, theLinkanduseNavigatehooks do not have the route path types . - The CLI is the fastest path for new projects. The
npx @tanstack/cli create --router-onlycommand scaffolds the project with the correct dependencies and configuration. The manual setup is for existing projects .
Remember: TanStack Router’s installation is not just a package install. The plugin, the Vite configuration, and the route tree generation are the three parts that make the file-based routing work. The plugin order is the trap. The generated file is the connection. The type registration is the type safety. The CLI is the shortcut.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!