Cursor Rules

tanstack router react - Claude MCP Skill

You are an expert in TanStack Router, React, TypeScript, and modern type-safe client-side routing.

SEO Guide: Enhance your AI agent with the tanstack router react tool. This Model Context Protocol (MCP) server allows Claude Desktop and other LLMs to you are an expert in tanstack router, react, typescript, and modern type-safe client-side routing.... Download and configure this skill to unlock new capabilities for your AI workflow.

🌟204 stars • 3372 forks
📥0 downloads

Documentation

SKILL.md
You are an expert in TanStack Router, React, TypeScript, and modern type-safe client-side routing.

# TanStack Router + React Guidelines

## Core Philosophy
- TanStack Router is 100% type-safe — leverage TypeScript generics for route params, search params, and loader data
- Prefer file-based routing for scalability; use code-based routing only for highly dynamic use cases
- Always define routes with `createFileRoute` or `createRootRoute` — never use plain objects
- Route data loading belongs in `loader` functions, not in component `useEffect`
- Search params are first-class citizens — define their schema with Zod or Valibot for validation and type inference

## Project Setup
- Use `@tanstack/react-router` with Vite and the `@tanstack/router-vite-plugin` for file-based routing
- Enable `routeTree.gen.ts` auto-generation — never manually edit this file
- Structure routes under `src/routes/` directory
- Root layout goes in `src/routes/__root.tsx`
- Use `src/routes/index.tsx` for the home/index route

## File-Based Route Conventions
```
src/routes/
  __root.tsx          ← Root layout (wraps all routes)
  index.tsx           ← / route
  about.tsx           ← /about route
  posts/
    index.tsx         ← /posts route
    $postId.tsx       ← /posts/:postId (dynamic segment)
    _layout.tsx       ← Layout route (no path segment)
  _auth/
    login.tsx         ← /login (grouped under auth layout)
  (admin)/
    dashboard.tsx     ← /dashboard (pathless group)
```

## Route Definition Patterns
```tsx
// src/routes/posts/$postId.tsx
import { createFileRoute } from '@tanstack/react-router'

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

function PostComponent() {
  const post = Route.useLoaderData() // type-safe loader data
  const { postId } = Route.useParams() // type-safe params
  return <div>{post.title}</div>
}
```

## Type-Safe Search Params
- Always define search param schemas using `z.object()` from Zod
- Use `validateSearch` option on route definition
- Access with `Route.useSearch()` — never read raw `window.location.search`
```tsx
import { z } from 'zod'
import { createFileRoute } from '@tanstack/react-router'

const searchSchema = z.object({
  page: z.number().int().min(1).default(1),
  q: z.string().optional(),
})

export const Route = createFileRoute('/search')({
  validateSearch: searchSchema,
  component: SearchPage,
})

function SearchPage() {
  const { page, q } = Route.useSearch()
  // ...
}
```

## Navigation
- Use `<Link>` from `@tanstack/react-router` — never `<a href>` for internal navigation
- Use `useNavigate()` for programmatic navigation
- Always pass typed `params` and `search` to Link — the compiler will catch mistakes
```tsx
import { Link, useNavigate } from '@tanstack/react-router'

// Declarative
<Link to="/posts/$postId" params={{ postId: '123' }}>View Post</Link>

// Programmatic
const navigate = useNavigate()
navigate({ to: '/posts/$postId', params: { postId: post.id } })
```

## Loaders & Data Fetching
- Use `loader` for data that must be available before render (no loading spinners for critical data)
- Integrate with TanStack Query by using `ensureQueryData` inside loaders for caching
- Use `staleTime` on loaders to avoid redundant fetches during navigation
- Return plain serializable data from loaders — no class instances
```tsx
export const Route = createFileRoute('/posts')({
  loader: ({ context: { queryClient } }) =>
    queryClient.ensureQueryData(postsQueryOptions()),
  component: PostsPage,
})
```

## Error Handling
- Define `errorComponent` on routes to handle loader or render errors
- Use `notFoundComponent` for 404 states within a route subtree
- Use `pendingComponent` for showing skeletons/spinners during data loading
```tsx
export const Route = createFileRoute('/posts/$postId')({
  loader: fetchPost,
  errorComponent: ({ error }) => <ErrorBanner message={error.message} />,
  pendingComponent: () => <PostSkeleton />,
  notFoundComponent: () => <NotFound />,
  component: PostDetail,
})
```

## Router Context
- Use router context to inject global dependencies (queryClient, auth, theme) into loaders
- Define context type in `__root.tsx` and pass it when creating the router
```tsx
// __root.tsx
import { createRootRouteWithContext } from '@tanstack/react-router'

interface RouterContext {
  queryClient: QueryClient
  auth: AuthState
}

export const Route = createRootRouteWithContext<RouterContext>()({
  component: RootLayout,
})

// main.tsx
const router = createRouter({
  routeTree,
  context: { queryClient, auth },
})
```

## Route Guards / Auth
- Use `beforeLoad` for authentication checks — redirect to login if unauthenticated
- Never put auth logic inside components — handle it at the routing layer
```tsx
export const Route = createFileRoute('/_auth/dashboard')({
  beforeLoad: ({ context }) => {
    if (!context.auth.isAuthenticated) {
      throw redirect({ to: '/login' })
    }
  },
  component: Dashboard,
})
```

## Performance
- Use `preload` on `<Link>` to trigger loader prefetching on hover/focus
- Set `defaultPreload: 'intent'` on the router for automatic preloading
- Use `gcTime` and `staleTime` on loaders to tune cache behavior
- Lazy-load route components with `React.lazy` for code splitting

## DevTools
- Install `@tanstack/router-devtools` and render `<TanStackRouterDevtools />` in development
- Use devtools to inspect route tree, active matches, loader data, and search params

## Testing
- Use `createMemoryHistory` and `createRouter` to create isolated router instances in tests
- Wrap components under test with `<RouterProvider router={testRouter} />`
- Mock loaders by providing fake context values

Signals

Avg rating0.0
Reviews0
Favorites0

Information

Repository
PatrickJS/awesome-cursorrules
Author
PatrickJS
Last Sync
5/12/2026
Repo Updated
5/12/2026
Created
5/12/2026

Reviews (0)

No reviews yet. Be the first to review this skill!