Skip to main content
skill CX Codex

router-plugin — Claude Code skill: what it does, how to install

Configures the TanStack Router bundler plugin for route generation and code splitting. Works across Vite, Webpack, Rspack, and esbuild setups.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add TanStack/router --skill router-plugin -a claude-code
Open on GitHub

What router-plugin does

This skill guides the setup of @tanstack/router-plugin across React, Solid, and Vue projects. The plugin tracks route files inside routesDirectory to generate routeTree.gen.ts. When autoCodeSplitting is enabled, it breaks route components and loaders into lazy chunks through virtual modules.

In Vite configurations, the router plugin must come before the framework plugin like react(). Wrong ordering causes route generation to fail silently. Never edit routeTree.gen.ts by hand. Update source route files instead and let the bundler or pnpm exec tsr generate rebuild the tree automatically.

What it helps with

  • generate routeTree.gen.ts from file-based routes
  • set up automatic code splitting via autoCodeSplitting
  • configure the router plugin for Vite, Webpack, Rspack, or esbuild
  • customize route file ignore patterns and split groupings

Example prompts for the agent

  • Show how to set up router-plugin before react() in vite.config.ts
  • Configure custom codeSplittingOptions for a specific routeId
  • Walk me through refactoring routesDirectory without breaking routeTree.gen.ts

How to install router-plugin

1Skills CLI (Vercel)

npx skills add TanStack/router --skill router-plugin -a claude-code

2Manually: put the files in place

~/.claude/skills/router-plugin/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/router-plugin/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about router-plugin

How to install router-plugin in Claude Code?

Run npx skills add TanStack/router --skill router-plugin -a claude-code in your terminal.

What does router-plugin do?

It compiles file-based routes into routeTree.gen.ts and splits route artifacts into lazy-loaded bundles.

Why does plugin ordering matter in Vite?

The tanstackRouter plugin must precede react() in the plugins array. Failing to order them correctly leads to silent route generation failures.

Source text

SKILL.md · MIT
---
name: router-plugin
description: >-
  TanStack Router bundler plugin for route generation and automatic
  code splitting. Supports Vite, Webpack, Rspack, and esbuild.
  Configures autoCodeSplitting, routesDirectory, target framework,
  and code split groupings.
metadata:
  type: core
  library: tanstack-router
  library_version: '1.168.23'
sources:
  - TanStack/router:packages/router-plugin/src
  - TanStack/router:docs/router/routing/file-based-routing.md
  - TanStack/router:docs/router/guide/code-splitting.md
---

# Router Plugin (`@tanstack/router-plugin`)

Bundler plugin that powers TanStack Router's file-based routing and automatic code splitting. Works with Vite, Webpack, Rspack, and esbuild via unplugin.

> **CRITICAL**: The router plugin MUST come before the framework plugin (React, Solid, Vue) in the Vite config. Wrong order causes route generation and code splitting to fail silently.

## Install

```bash
npm install -D @tanstack/router-plugin
```

## Bundler Setup

### Vite (most common)

```ts
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { tanstackRouter } from '@tanstack/router-plugin/vite'

export default defineConfig({
  plugins: [
    // MUST come before react()
    tanstackRouter({
      target: 'react',
      autoCodeSplitting: true,
    }),
    react(),
  ],
})
```

### Webpack

```ts
// webpack.config.js
const { tanstackRouter } = require('@tanstack/router-plugin/webpack')

module.exports = {
  plugins: [
    tanstackRouter({
      target: 'react',
      autoCodeSplitting: true,
    }),
  ],
}
```

### Rspack

```ts
// rspack.config.js
const { tanstackRouter } = require('@tanstack/router-plugin/rspack')

module.exports = {
  plugins: [
    tanstackRouter({
      target: 'react',
      autoCodeSplitting: true,
    }),
  ],
}
```

### esbuild

```ts
import { tanstackRouter } from '@tanstack/router-plugin/esbuild'
import esbuild from 'esbuild'

esbuild.build({
  plugins: [
    tanstackRouter({
      target: 'react',
      autoCodeSplitting: true,
    }),
  ],
})
```

## Configuration Options

### Core Options

| Option               | Type                          | Default                    | Description                      |
| -------------------- | ----------------------------- | -------------------------- | -------------------------------- |
| `target`             | `'react' \| 'solid' \| 'vue'` | `'react'`                  | Target framework                 |
| `routesDirectory`    | `string`                      | `'./src/routes'`           | Directory containing route files |
| `generatedRouteTree` | `string`                      | `'./src/routeTree.gen.ts'` | Path for generated route tree    |
| `autoCodeSplitting`  | `boolean`                     | `undefined`                | Enable automatic code splitting  |

### File Convention Options

| Option                   | Type                                                    | Default     | Description                          |
| ------------------------ | ------------------------------------------------------- | ----------- | ------------------------------------ |
| `routeFilePrefix`        | `string`                                                | `undefined` | Prefix filter for route files        |
| `routeFileIgnorePrefix`  | `string`                                                | `'-'`       | Prefix to exclude files from routing |
| `routeFileIgnorePattern` | `string`                                                | `undefined` | Pattern to exclude from routing      |
| `indexToken`             | `string \| RegExp \| { regex: string; flags?: string }` | `'index'`   | Token identifying index routes       |
| `routeToken`             | `string \| RegExp \| { regex: string; flags?: string }` | `'route'`   | Token identifying route config files |

### Code Splitting Options

```ts
tanstackRouter({
  target: 'react',
  autoCodeSplitting: true,
  codeSplittingOptions: {
    // Default groupings for all routes
    defaultBehavior: [['component'], ['errorComponent'], ['notFoundComponent']],

    // Per-route custom splitting
    splitBehavior: ({ routeId }) => {
      if (routeId === '/dashboard') {
        // Keep loader and component together for dashboard
        return [['loader', 'component'], ['errorComponent']]
      }
      // Return undefined to use defaultBehavior
    },
  },
})
```

### Output Options

| Option                      | Type                   | Default    | Description                      |
| --------------------------- | ---------------------- | ---------- | -------------------------------- |
| `quoteStyle`                | `'single' \| 'double'` | `'single'` | Quote style in generated code    |
| `semicolons`                | `boolean`              | `false`    | Use semicolons in generated code |
| `disableTypes`              | `boolean`              | `false`    | Disable TypeScript types         |
| `disableLogging`            | `boolean`              | `false`    | Suppress plugin logs             |
| `addExtensions`             | `boolean \| string`    | `false`    | Add file extensions to imports   |
| `enableRouteTreeFormatting` | `boolean`              | `true`     | Format generated route tree      |

### Virtual Route Config

```ts
import { routes } from './routes'

tanstackRouter({
  target: 'react',
  virtualRouteConfig: routes, // or './routes.ts'
})
```

## How It Works

The composed plugin assembles up to 3 sub-plugins:

1. **Route Generator** (always) — Watches route files and generates `routeTree.gen.ts`
2. **Code Splitter** (when `autoCodeSplitting: true`) — Splits route files into lazy-loaded chunks using virtual modules
3. **HMR** (dev mode, when code splitter is off) — Hot-reloads route changes without full refresh

## Route Refactor Workflow

When moving, renaming, adding, or deleting file routes:

1. Change the source files under `routesDirectory`. Keep the exported route identifier named `Route`.
2. Let the bundler plugin regenerate the tree, or run `pnpm exec tsr generate` when the project uses the CLI.
3. Inspect the generated diff for the expected route IDs, parents, paths, and imports. Never repair `routeTree.gen.ts` by hand.
4. Update links, redirects, `from` narrowing, params, preload calls, and tests that reference the old route.
5. Run route-generation tests, type tests, and a production build. A passing editor typecheck does not prove the plugin generated or split the new route correctly.

Commit `routeTree.gen.ts`; it is generated source used by the application at runtime.

## Individual Plugin Exports

For advanced use, each sub-plugin is exported separately from the Vite entry:

```ts
import {
  tanstackRouter, // Composed (default)
  tanstackRouterGenerator, // Generator only
  tanStackRouterCodeSplitter, // Code splitter only
} from '@tanstack/router-plugin/vite'
```

## Common Mistakes

### 1. CRITICAL: Wrong plugin order in Vite config

The router plugin must come before the framework plugin. Otherwise, route generation and code splitting fail silently.

```ts
// WRONG — react() before tanstackRouter()
plugins: [react(), tanstackRouter({ target: 'react' })]

// CORRECT — tanstackRouter() first
plugins: [tanstackRouter({ target: 'react' }), react()]
```

### 2. HIGH: Missing target option for non-React frameworks

The `target` defaults to `'react'`. For Solid or Vue, you must set it explicitly.

```ts
// WRONG for Solid — generates React imports
tanstackRouter({ autoCodeSplitting: true })

// CORRECT for Solid
tanstackRouter({ target: 'solid', autoCodeSplitting: true })
```

### 3. MEDIUM: Confusing autoCodeSplitting with manual lazy routes

When `autoCodeSplitting` is enabled, the plugin handles splitting automatically. You do NOT need manual `createLazyRoute` or `lazyRouteComponent` calls — the plugin transforms your route files at build time.

```tsx
// WRONG — manual lazy loading with autoCodeSplitting enabled
const LazyAbout = lazyRouteComponent(() => import('./about'))

// CORRECT — just write normal route files, plugin handles splitting
// src/routes/about.tsx
export const Route = createFileRoute('/about')({
  component: AboutPage,
})

function AboutPage() {
  return <h1>About</h1>
}
```

### 4. HIGH: Editing the generated route tree

Changes to `routeTree.gen.ts` are overwritten and can leave source routes, generated types, and runtime routing out of sync. Fix route filenames or plugin configuration, regenerate, and verify the generated diff instead.

## Cross-References

- `@tanstack/router-core#router-core/code-splitting` — manual code splitting concepts
- `@tanstack/virtual-file-routes#virtual-file-routes` — programmatic route trees

© TanStack · MIT · TanStack/router

Similar skills

Everything for Frontend and UI →

From the same set7

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor