---
name: tanstack-router
description: "Type-safe, file-based routing for React with TanStack Router. Use when defining routes with createFileRoute, validating search params with Zod, writing route loaders, setting up auth guards with beforeLoad, integrating TanStack Query into loaders, or configuring router context and preloading."
---
# TanStack Router
TanStack Router is a fully type-safe router for React that treats routes, loaders, params, and search params as first-class typed data rather than untyped strings.
## Workflow for Adding a New Route
1. **Create the route file** — Add a file under `src/routes/` following the file-based routing convention (see below).
2. **Define the route** — Export `Route` from `createFileRoute('/path')({...})` with `component`, and optionally `loader`, `validateSearch`, `beforeLoad`, `errorComponent`, and `pendingComponent`.
3. **Validate search params** — If the route reads query params, define a Zod schema and pass it as `validateSearch`.
4. **Load data** — Fetch data in `loader`, not in a component `useEffect`; integrate with TanStack Query via `queryClient.ensureQueryData` when caching is needed.
5. **Guard access** — Add `beforeLoad` checks (e.g. auth) that `throw redirect({ to: '/login' })` when a precondition fails.
6. **Link to the route** — Navigate with `` so the compiler validates params and search at every call site.
7. **Regenerate the route tree** — Ensure `routeTree.gen.ts` is regenerated (automatic under the Vite plugin's dev server / build) before running or building the app.
## Core Principles
- TanStack Router is 100% type-safe — lean on TypeScript generics for params, search params, and loader data instead of manual casting.
- Prefer file-based routing with `@tanstack/router-vite-plugin` (or `@tanstack/router-plugin/vite`) for scalability over manually constructed route trees.
- Always define routes with `createFileRoute` (leaf/nested routes) or `createRootRoute` / `createRootRouteWithContext` (root).
- Route data loading belongs in `loader` functions, not in component `useEffect` — this enables preloading, parallel loading, and pending/error states.
- Search params are first-class state — always define their schema with Zod (or another standard-schema validator) so they are typed and validated on every read.
## File-Based Route Conventions
```
src/routes/
__root.tsx ← Root layout
index.tsx ← / route
posts/
index.tsx ← /posts
$postId.tsx ← /posts/:postId (dynamic segment)
_layout.tsx ← Layout route (no path segment)
_auth/ ← Pathless auth layout group
dashboard.tsx
```
- A leading underscore on a segment (`_layout`, `_auth`) creates a pathless layout route used purely for grouping/shared UI.
- A `$` prefix (`$postId`) marks a dynamic path segment, matching `Route.useParams()`.
- `index.tsx` inside a folder matches the folder's own path with no additional segment.
## Route Definition
```tsx
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params }) => fetchPost(params.postId),
component: PostComponent,
errorComponent: ({ error }) => ,
pendingComponent: () => ,
})
function PostComponent() {
const post = Route.useLoaderData() // type-safe
const { postId } = Route.useParams() // type-safe
return