# TanStack Router & TanStack Start
TanStack Router is a fully type-safe, framework-agnostic routing library for React, Solid, and Vue applications. It offers end-to-end TypeScript inference across route paths, path parameters, search parameters, and loader data — all without manual type annotations. It provides built-in SWR caching for route loaders, nested layout support, deferred data loading with streaming, file-based route generation, and schema-driven search param validation via Zod, Valibot, ArkType, or Effect/Schema. The library is available as `@tanstack/react-router`, `@tanstack/solid-router`, and `@tanstack/vue-router`.
TanStack Start is the companion full-stack framework built on top of TanStack Router. It adds full-document SSR and streaming, type-safe server functions (RPC), middleware, deployment-ready Vite/Rsbuild builds, and React Server Components support. The packages `@tanstack/react-start`, `@tanstack/solid-start`, and `@tanstack/vue-start` extend their respective router packages with server capabilities. Together, Router and Start form a cohesive solution covering everything from client-side routing through to production-ready server rendering.
---
## `createRouter` — Create a router instance
Creates and configures the central router instance that manages the entire route tree. The `routeTree` is the only required option. After creating the router, register its type globally via TypeScript declaration merging to enable full project-wide type inference.
```tsx
// src/router.tsx
import { createRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen' // auto-generated by file-based routing
export const router = createRouter({
routeTree,
defaultPreload: 'intent', // preload routes on link hover
defaultStaleTime: 10_000, // cache loader data for 10 s by default
defaultPreloadStaleTime: 0, // always re-run loaders when used with external cache
context: {
queryClient, // pass any context down to all routes
},
})
// Register the router type once — unlocks full TypeScript inference everywhere
declare module '@tanstack/react-router' {
interface Register {
router: typeof router
}
}
```
---
## File-Based Route Structure — Filesystem conventions
TanStack Router generates a type-safe route tree from files inside `src/routes/`. Special prefixes and suffixes control nesting, layouts, path params, and lazy loading.
```
src/routes/
├── __root.tsx # Always-rendered root layout
├── index.tsx # Matches "/"
├── about.tsx # Matches "/about"
├── posts.tsx # Layout for "/posts/*"
├── posts/
│ ├── index.tsx # Matches "/posts" (exact)
│ ├── $postId.tsx # Matches "/posts/:postId"
│ └── $postId.edit.tsx # Matches "/posts/:postId/edit"
├── _auth.tsx # Pathless layout (no URL segment)
├── _auth/
│ └── dashboard.tsx # Matches "/dashboard" (wrapped in _auth)
└── files.$.tsx # Wildcard splat: "/files/*"
```
Flat-file alternative using `.` notation:
```
posts.$postId.tsx → /posts/:postId
settings.profile.tsx → /settings/profile
_pathlessLayout.route-a.tsx → /route-a (inside pathless layout)
```
---
## `createFileRoute` — Define a file-based route
Used inside every file under `src/routes/`. Accepts the route path as a type parameter and returns a route definition object. Supports `loader`, `beforeLoad`, `validateSearch`, `component`, `errorComponent`, `pendingComponent`, and more.
```tsx
// src/routes/posts/$postId.tsx
import { createFileRoute } from '@tanstack/react-router'
import { z } from 'zod'
export const Route = createFileRoute('/posts/$postId')({
// Validate search params with Zod — types are inferred automatically
validateSearch: z.object({
tab: z.enum(['details', 'comments', 'related']).catch('details'),
}),
// Declare which search params the loader depends on (for cache keying)
loaderDeps: ({ search: { tab } }) => ({ tab }),
// Fetch data before rendering; receives params, deps, context, abortController
loader: async ({ params: { postId }, deps: { tab }, abortController }) => {
const [post, tabData] = await Promise.all([
fetchPost(postId, { signal: abortController.signal }),
fetchTabData(postId, tab, { signal: abortController.signal }),
])
return { post, tabData }
},
// Show this while loader is pending (after 1 s threshold)
pendingComponent: () => ,
// Render when an error occurs
errorComponent: ({ error, reset }) => (
}
```
---
## `createRootRoute` / `createRootRouteWithContext` — Define the root route
Creates the top-level route that wraps every other route. Use `createRootRouteWithContext()` to inject typed context (e.g., auth state, query client) that is available to all descendant routes.
```tsx
// src/routes/__root.tsx
import {
createRootRouteWithContext,
Outlet,
Link,
} from '@tanstack/react-router'
import type { QueryClient } from '@tanstack/react-query'
interface RouterContext {
queryClient: QueryClient
auth: { isAuthenticated: boolean; user: User | null }
}
export const Route = createRootRouteWithContext()({
// 404 handler — shown when no route matches
notFoundComponent: () =>
Page not found
,
component: RootLayout,
})
function RootLayout() {
return (