Skip to main content
tanstack-router Use when setting up routes, implementing navigation, or configuring route loaders. TanStack Router patterns for type-safe, file-based routing. Covers installation, route configuration, typed params/search, layouts, and navigation.
Jump to install Skills Marketplace Discover and explore AI skills built by the community.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Copy promptShow prompt details A direct command skips the review prompt. Inspect the source before running it.
npx skills add https://github.com/MadAppGang/claude-code --skill tanstack-routerThe command stays on one line. Scroll horizontally to inspect it before copying.
Prefer a local copy? Download the files currently available to SkillsMP.
Download Zip Downloading... Related occupations
SOC
Based on SOC occupation classification
name tanstack-router description Use when setting up routes, implementing navigation, or configuring route loaders. TanStack Router patterns for type-safe, file-based routing. Covers installation, route configuration, typed params/search, layouts, and navigation. updated "2026-01-20T00:00:00.000Z" keywords tanstack-router, routing, file-based-routing, type-safe, navigation, layouts, params
TanStack Router Patterns
Type-safe, file-based routing for React applications with TanStack Router.
Installation
pnpm add @tanstack/react-router
pnpm add -D @tanstack/router-plugin
import { TanStackRouterVite } from '@tanstack/router-plugin/vite'
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig ({
plugins : [
react (),
(),
],
})
TanStackRouterVite
Bootstrap
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
}
}
ReactDOM .createRoot (document .getElementById ('root' )!).render (
<StrictMode >
<RouterProvider router ={router} />
</StrictMode >
)
File-Based Routes src/routes/
โโโ __root.tsx # Root layout (Outlet, providers)
โโโ index.tsx # "/" route
โโโ about.tsx # "/about" route
โโโ users/
โ โโโ index.tsx # "/users" route
โ โโโ $userId.tsx # "/users/:userId" route (dynamic)
โโโ posts/
โโโ $postId/
โ โโโ index.tsx # "/posts/:postId" route
โ โโโ edit.tsx # "/posts/:postId/edit" route
โโโ index.tsx # "/posts" route
__root.tsx - Root layout (contains <Outlet />)
index.tsx - Index route for that path
$param.tsx - Dynamic parameter (e.g., $userId โ :userId)
_layout.tsx - Layout route (no URL segment)
route.lazy.tsx - Lazy-loaded route
Root Layout
import { createRootRoute, Outlet } from '@tanstack/react-router'
import { TanStackRouterDevtools } from '@tanstack/router-devtools'
export const Route = createRootRoute ({
component : () => (
<>
<nav >
<Link to ="/" > Home</Link >
<Link to ="/about" > About</Link >
<Link to ="/users" > Users</Link >
</nav >
<main >
<Outlet /> {/* Child routes render here */}
</main >
<TanStackRouterDevtools /> {/* Auto-hides in production */}
</>
),
})
Basic Route
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute ('/about' )({
component : AboutComponent ,
})
function AboutComponent ( ) {
return <div > About Page</div >
}
Dynamic Routes with Params
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute ('/users/$userId' )({
component : UserComponent ,
})
function UserComponent ( ) {
const { userId } = Route .useParams ()
return <div > User ID: {userId}</div >
}
Typed Search Params
import { createFileRoute } from '@tanstack/react-router'
import { z } from 'zod'
const userSearchSchema = z.object ({
page : z.number ().default (1 ),
filter : z.enum (['active' , 'inactive' , 'all' ]).default ('all' ),
search : z.string ().optional (),
})
export const Route = createFileRoute ('/users/' )({
validateSearch : userSearchSchema,
component : UsersComponent ,
})
function UsersComponent ( ) {
const { page, filter, search } = Route .useSearch ()
return (
<div >
<p > Page: {page}</p >
<p > Filter: {filter}</p >
{search && <p > Search: {search}</p > }
</div >
)
}
Navigation with Link import { Link } from '@tanstack/react-router'
<Link to="/about" >About </Link >
<Link to ="/users/$userId" params ={{ userId: '123 ' }}>
View User
</Link >
<Link
to ="/users"
search ={{ page: 2 , filter: 'active ' }}
>
Users Page 2
</Link >
<Link to ="/details" state ={{ from: 'home ' }}>
Details
</Link >
<Link
to ="/about"
activeProps ={{ className: 'text-blue-600 font-bold ' }}
inactiveProps ={{ className: 'text-gray-600 ' }}
>
About
</Link >
Programmatic Navigation import { useNavigate } from '@tanstack/react-router'
function MyComponent ( ) {
const navigate = useNavigate ()
const handleClick = ( ) => {
navigate ({ to : '/users' })
navigate ({ to : '/users/$userId' , params : { userId : '123' } })
navigate ({ to : '/users' , search : { page : 2 } })
navigate ({ to : '/login' , replace : true })
navigate ({ to : '..' })
}
return <button onClick ={handleClick} > Navigate</button >
}
Route Loaders (Data Fetching)
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute ('/users/$userId' )({
loader : async ({ params }) => {
const user = await fetchUser (params.userId )
return { user }
},
component : UserComponent ,
})
function UserComponent ( ) {
const { user } = Route .useLoaderData ()
return <div > {user.name}</div >
}
With TanStack Query Integration (see router-query-integration skill for details):
import { queryClient } from '@/app/queryClient'
import { userQuery Options } from '@/features/users/queries'
export const Route = createFileRoute ('/users/$userId' )({
loader : ({ params } ) =>
queryClient.ensureQueryData (userQueryOptions (params.userId )),
component : UserComponent ,
})
Layouts Layout Route (_layout.tsx - no URL segment):
import { createFileRoute, Outlet } from '@tanstack/react-router'
export const Route = createFileRoute ('/_layout' )({
component : LayoutComponent ,
})
function LayoutComponent ( ) {
return (
<div className ="dashboard-layout" >
<Sidebar />
<div className ="content" >
<Outlet /> {/* Child routes */}
</div >
</div >
)
}
Loading States export const Route = createFileRoute ('/users' )({
loader : async () => {
const users = await fetchUsers ()
return { users }
},
pendingComponent : () => <Spinner /> ,
errorComponent : ({ error } ) => <ErrorMessage > {error.message}</ErrorMessage > ,
component : UsersComponent ,
})
Error Handling import { ErrorComponent } from '@tanstack/react-router'
export const Route = createFileRoute ('/users' )({
loader : async () => {
const users = await fetchUsers ()
if (!users) throw new Error ('Failed to load users' )
return { users }
},
errorComponent : ({ error, reset } ) => (
<div >
<h1 > Error loading users</h1 >
<p > {error.message}</p >
<button onClick ={reset} > Try Again</button >
</div >
),
component : UsersComponent ,
})
Route Context
export const Route = createRootRoute ({
beforeLoad : () => ({
user : getCurrentUser (),
}),
component : RootComponent ,
})
export const Route = createFileRoute ('/dashboard' )({
component : function Dashboard ( ) {
const { user } = Route .useRouteContext ()
return <div > Welcome, {user.name}</div >
},
})
Route Guards / Auth
import { createFileRoute, redirect } from '@tanstack/react-router'
export const Route = createFileRoute ('/_authenticated' )({
beforeLoad : ({ context } ) => {
if (!context.user ) {
throw redirect ({ to : '/login' })
}
},
component : Outlet ,
})
Preloading <Link
to="/users/$userId"
params={{ userId : '123' }}
preload="intent"
>
View User
</Link >
preload="intent" - Preload on hover/focus
preload="render" - Preload when link renders
preload={false} - No preload (default)
DevTools import { TanStackRouterDevtools } from '@tanstack/router-devtools'
<TanStackRouterDevtools position="bottom-right" />
Auto-hides in production builds.
Best Practices
Use Type-Safe Navigation - Let TypeScript catch routing errors at compile time
Validate Search Params - Use Zod schemas for search params
Prefetch Data in Loaders - Integrate with TanStack Query for optimal data fetching
Use Layouts for Shared UI - Avoid duplicating layout code across routes
Lazy Load Routes - Use route.lazy.tsx for code splitting
Leverage Route Context - Share data down the route tree efficiently
Common Patterns
export const Route = createFileRoute ('/$' )({
component : () => <div > 404 Not Found</div > ,
})
const searchSchema = z.object ({
optional : z.string ().optional (),
})
Multi-Level Dynamic Routes:
/posts/$postId/comments/$commentId
Related Skills
tanstack-query - Data fetching and caching
router-query-integration - Integrating Router loaders with Query
core-principles - Project structure with routes
More from this repository