Token导航 LogoToken导航

Agent Skill · 研究检索

tanstack-router-migration(tanstack 路由器迁移)

tanstack-router-migration 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

tanstack-router-migration 是研究检索类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证为 MIT,第三方扫描已通过,按安装量在研究检索类的 73,675 个 Skill 里排第 39,386。

总安装 1,420周安装 61GitHub Stars 4,321下载 498核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
MIT

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:tanstack-router-migration(tanstack 路由器迁移)
来源仓库:https://github.com/redpanda-data/console
仓库路径:skills/tanstack-router-migration
安装命令:
npx skills add https://github.com/redpanda-data/console --skill tanstack-router-migration
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/redpanda-data/console --skill tanstack-router-migration

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

tanstack-router-migration 用于查找、检索和筛选相关信息,适合在 Codex、Claude 等宿主中处理技术迁移问题。适用于研究检索场景,可协助分析路由升级路径和兼容性问题。通过 npx skills add 命令安装,需确认是否涉及代码修改或依赖变更。

使用前建议核实仓库维护状态,避免引入不稳定因素。适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

来源仓库内路径:skills/tanstack-router-migration

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/redpanda-data/console --skill tanstack-router-…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

tanstack-router-migration 怎么安装?

在终端执行 npx skills add https://github.com/redpanda-data/console --skill tanstack-router-migration。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

tanstack-router-migration 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

tanstack-router-migration 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

tanstack-router-migration 是免费的吗?

来源标注的许可证是 MIT。本站不代收任何费用,也不托管安装包;能否商用、要不要署名,以许可证原文为准。

tanstack-router-migration 用的人多吗?

公开数据是累计安装 1,420 次,近一周安装 61 次,下载 498 次,GitHub 4,321 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

tanstack-router-migration 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 3 个目录同时收录,说明这个 Skill 流传比较广。
  • 许可证明确为 MIT,商用和分发边界好判断。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理研究检索类任务、又不想每次都手写提示词的人。
  • 需要许可证清楚、并且有第三方扫描结果的团队项目。

不太适合

  • 需要厂商级技术支持和 SLA 的生产系统。

研究检索类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
find-skills

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
tanstack-router-migration

tanstack 路由器迁移 · 本页

1,4204,321需要联网MIT通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

React Router to TanStack Router Migration

Migrate React applications from React Router to TanStack Router with file-based routing. This skill provides a structured approach for both incremental and clean migrations.

Critical Rules

ALWAYS:

  • Use file-based routing with routes in src/routes/ directory
  • Use from parameter in all hooks for type safety (useParams({from: '/path'}))
  • Validate search params with Zod schemas using @tanstack/zod-adapter
  • Configure build tool plugin before creating routes
  • Register router type for full TypeScript inference
  • Use fallback() wrapper for optional search params

NEVER:

  • Edit routeTree.gen.ts (auto-generated file)
  • Use React Router hooks in new code during migration
  • Forget the from parameter (loses type safety)
  • Use string-only validation for search params
  • Skip the build plugin configuration

Dependencies

# Core dependencies
bun add @tanstack/react-router @tanstack/zod-adapter

# Build plugin (choose one based on your bundler)
bun add -d @tanstack/router-plugin

# Optional integrations
bun add nuqs                    # URL state management
bun add @sentry/react           # Error tracking with router integration

Migration Phases

Phase 1: Assessment

Audit existing React Router usage:

# Find all React Router imports
grep -r "from 'react-router" src/ --include="*.tsx" --include="*.ts"
grep -r 'from "react-router' src/ --include="*.tsx" --include="*.ts"

# Find hook usages
grep -r "useParams\|useSearchParams\|useNavigate\|useLocation\|useMatch" src/

Document:

  • React Router version (v5 or v6)
  • Number of routes
  • useParams usage count
  • useSearchParams usage count
  • useNavigate usage count
  • Custom Link components
  • Route guards/protected routes
  • Existing route structure

Phase 2: Setup

1. Configure Build Tool

See references/build-configuration.md for full configs.

Rspack/Rsbuild:

// rsbuild.config.ts
import { TanStackRouterRspack } from '@tanstack/router-plugin/rspack';

export default {
  tools: {
    rspack: (config) => {
      config.plugins?.push(
        TanStackRouterRspack({
          target: 'react',
          autoCodeSplitting: true,
          routesDirectory: './src/routes',
          generatedRouteTree: './src/routeTree.gen.ts',
          quoteStyle: 'single',
          semicolons: true,
        })
      );
      // Prevent rebuild loop
      config.watchOptions = { ignored: ['**/routeTree.gen.ts'] };
      return config;
    },
  },
};

Vite:

// vite.config.ts
import { TanStackRouterVite } from '@tanstack/router-plugin/vite';

export default defineConfig({
  plugins: [
    TanStackRouterVite({
      target: 'react',
      autoCodeSplitting: true,
      routesDirectory: './src/routes',
      generatedRouteTree: './src/routeTree.gen.ts',
    }),
    react(),
  ],
});

2. Configure Linter

// biome.jsonc or eslint config
{
  "files": {
    "ignore": ["**/routeTree.gen.ts"]
  },
  "overrides": [
    {
      "include": ["**/routes/**/*"],
      "linter": {
        "rules": {
          "style": {
            "useFilenamingConvention": "off"  // Allow $param.tsx naming
          }
        }
      }
    }
  ]
}

3. Create Routes Directory

mkdir -p src/routes

Phase 3: Router Creation

Create Router Instance:

// src/app.tsx
import { createRouter, RouterProvider } from '@tanstack/react-router';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { routeTree } from './routeTree.gen';
import { NotFoundPage } from './components/misc/not-found-page';

const queryClient = new QueryClient();

const router = createRouter({
  routeTree,
  context: {
    basePath: getBasePath(),
    queryClient,
  },
  basepath: getBasePath(),
  trailingSlash: 'never',
  defaultNotFoundComponent: NotFoundPage,
});

// Register router type for full TypeScript inference
declare module '@tanstack/react-router' {
  interface Register {
    router: typeof router;
  }

  // Extend HistoryState for typed navigation state
  interface HistoryState {
    // Add your custom state properties here
    returnUrl?: string;
    documentId?: string;
    documentName?: string;
  }
}

export function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <RouterProvider router={router} />
    </QueryClientProvider>
  );
}

Define Router Context Type:

// src/routes/__root.tsx
import type { QueryClient } from '@tanstack/react-query';

export type RouterContext = {
  basePath: string;
  queryClient: QueryClient;
};

Phase 4: Route Migration

Create Root Layout:

// src/routes/__root.tsx
import { createRootRouteWithContext, Outlet } from '@tanstack/react-router';
import { TanStackRouterDevtools } from '@tanstack/react-router-devtools';
import type { QueryClient } from '@tanstack/react-query';
import { NuqsAdapter } from 'nuqs/adapters/tanstack-router';

export type RouterContext = {
  basePath: string;
  queryClient: QueryClient;
};

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

function RootLayout() {
  return (
    <>
      <NuqsAdapter>
        <ErrorBoundary>
          <AppLayout>
            <Outlet />
          </AppLayout>
        </ErrorBoundary>
      </NuqsAdapter>
      {process.env.NODE_ENV === 'development' && (
        <TanStackRouterDevtools position="bottom-right" />
      )}
    </>
  );
}

File-Based Route Structure:

src/routes/
├── __root.tsx                    # Root layout
├── index.tsx                     # / (root redirect)
├── overview/
│   └── index.tsx                 # /overview
├── topics/
│   ├── index.tsx                 # /topics
│   └── $topicName/
│       ├── index.tsx             # /topics/:topicName
│       └── edit.tsx              # /topics/:topicName/edit
├── security/
│   ├── index.tsx                 # /security (redirect)
│   ├── acls/
│   │   ├── index.tsx             # /security/acls
│   │   ├── create.tsx            # /security/acls/create
│   │   └── $aclName/
│   │       └── details.tsx       # /security/acls/:aclName/details

See references/route-templates.md for complete templates.

Phase 5: Hook Migration

React RouterTanStack Router
useParams()useParams({from: '/path/$param'})
useSearchParams()routeApi.useSearch() with Zod validation
useNavigate()useNavigate({from: '/path'})
useLocation()useLocation() (same API)
<Link to="/path"><Link to="/path"> (type-safe)
<Navigate to="/path" /><Navigate to="/path" />

See references/migration-patterns.md for detailed before/after examples.

Navigation State:

Pass typed state between routes using HistoryState:

// Navigating with state
const navigate = useNavigate();
navigate({
  to: '/documents/$documentId',
  params: { documentId },
  state: {
    returnUrl: location.pathname,
    documentName: 'My Document',
  },
});

// Reading state in destination component
import { useLocation } from '@tanstack/react-router';

function DocumentPage() {
  const location = useLocation();
  const { returnUrl, documentName } = location.state;
  // Use state values...
}

useParams Migration:

// Before (React Router)
import { useParams } from 'react-router-dom';
const { id } = useParams<{ id: string }>();

// After (TanStack Router)
import { useParams } from '@tanstack/react-router';
const { id } = useParams({ from: '/items/$id' });

useSearch with Zod Validation:

// In route file
import { fallback, zodValidator } from '@tanstack/zod-adapter';
import { z } from 'zod';

const searchSchema = z.object({
  tab: fallback(z.string().optional(), undefined),
  page: fallback(z.number().optional(), 1),
  q: fallback(z.string().optional(), undefined),
});

export const Route = createFileRoute('/items/')({
  validateSearch: zodValidator(searchSchema),
  component: ItemsPage,
});

// In component
import { getRouteApi, useNavigate } from '@tanstack/react-router';

const routeApi = getRouteApi('/items/');

function ItemsPage() {
  const { tab, page, q } = routeApi.useSearch();
  const navigate = useNavigate({ from: '/items/' });

  const handleTabChange = (newTab: string) => {
    navigate({ search: (prev) => ({ ...prev, tab: newTab }) });
  };
}

Phase 6: Testing

Create Test Utilities:

// src/test-utils.tsx
import { createMemoryHistory, createRouter, RouterProvider } from '@tanstack/react-router';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { render, type RenderOptions } from '@testing-library/react';
import { routeTree } from './routeTree.gen';
import type { RouterContext } from './routes/__root';

interface RenderWithFileRoutesOptions extends Omit<RenderOptions, 'wrapper'> {
  initialLocation?: string;
  routerContext?: Partial<RouterContext>;
}

export function renderWithFileRoutes(
  ui: React.ReactElement | null = null,
  { initialLocation = '/', routerContext = {}, ...renderOptions }: RenderWithFileRoutesOptions = {}
) {
  const queryClient = new QueryClient({
    defaultOptions: { queries: { retry: false } },
  });

  const router = createRouter({
    routeTree,
    history: createMemoryHistory({ initialEntries: [initialLocation] }),
    context: { basePath: '', queryClient, ...routerContext },
  });

  function Wrapper({ children }: { children: React.ReactNode }) {
    return (
      <QueryClientProvider client={queryClient}>
        <RouterProvider router={router}>{children}</RouterProvider>
      </QueryClientProvider>
    );
  }

  return {
    ...render(ui ?? <div />, { wrapper: Wrapper, ...renderOptions }),
    router,
  };
}

export async function renderRoute(location: string, options?: RenderWithFileRoutesOptions) {
  const result = renderWithFileRoutes(null, { initialLocation: location, ...options });
  await result.router.load();
  return result;
}

Configure Vitest:

// vitest.config.integration.mts
import { tanstackRouter } from '@tanstack/router-plugin/vite';

export default defineConfig({
  plugins: [
    tanstackRouter({
      target: 'react',
      routesDirectory: './src/routes',
      generatedRouteTree: './src/routeTree.gen.ts',
    }),
    react(),
  ],
  test: {
    environment: 'jsdom',
    setupFiles: ['./src/test/setup.ts'],
  },
});

Phase 7: Integrations

Sentry Integration:

// src/app.tsx
import * as Sentry from '@sentry/react';

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  integrations: [
    Sentry.tanstackRouterBrowserTracingIntegration(router),
  ],
  tracesSampleRate: 1.0,
});

nuqs Integration:

// src/routes/__root.tsx
import { NuqsAdapter } from 'nuqs/adapters/tanstack-router';

function RootLayout() {
  return (
    <NuqsAdapter>
      <Outlet />
    </NuqsAdapter>
  );
}

Incremental Migration (Legacy Compatibility):

See references/incremental-migration.md for patterns to run both routers together during migration.

Quick Reference

Route File Naming

PatternFileURL
Index routetopics/index.tsx/topics
Dynamic paramtopics/$topicName.tsx/topics/:topicName
Nested dynamictopics/$topicName/edit.tsx/topics/:topicName/edit
Pathless layout_layout.tsx(no URL segment)
Catch-all$.tsx/*

Common Zod Patterns

import { fallback, zodValidator } from '@tanstack/zod-adapter';
import { z } from 'zod';

const searchSchema = z.object({
  // Optional string with undefined default
  tab: fallback(z.string().optional(), undefined),

  // Optional number with default value
  page: fallback(z.number().optional(), 1),

  // Required string
  id: z.string(),

  // Enum with default
  sort: fallback(z.enum(['asc', 'desc']).optional(), 'asc'),

  // Boolean
  expanded: fallback(z.boolean().optional(), false),
});

Trailing Slash in from Parameter

The from parameter must exactly match the route path as defined:

// Index routes (files named index.tsx) include trailing slash:
useParams({ from: '/topics/$topicName/' })  // Route: topics/$topicName/index.tsx

// Non-index routes do NOT include trailing slash:
useParams({ from: '/topics/$topicName/edit' })  // Route: topics/$topicName/edit.tsx

Type-Safe Navigation

// With params
<Link to="/topics/$topicName" params={{ topicName: 'my-topic' }}>
  View Topic
</Link>

// With search params
<Link to="/topics" search={{ page: 2, sort: 'desc' }}>
  Page 2
</Link>

// Programmatic navigation
const navigate = useNavigate({ from: '/topics/$topicName' });
navigate({
  to: '/topics/$topicName/edit',
  params: { topicName },
  search: { tab: 'settings' },
});

Checklist

Pre-Migration

  • Dependencies installed (@tanstack/react-router, @tanstack/router-plugin, @tanstack/zod-adapter)
  • Build tool plugin configured
  • Linter configured to allow $param.tsx naming
  • src/routes/ directory created

Route Migration

  • __root.tsx created with providers and layout
  • index.tsx created for root redirect
  • All routes migrated to file-based structure
  • Search params validated with Zod schemas
  • staticData added for titles/icons

Hook Migration

  • All useParams calls updated with from parameter
  • All useSearchParams replaced with routeApi.useSearch()
  • All useNavigate calls updated with from parameter
  • All Link components verified working

Testing

  • renderWithFileRoutes utility created
  • Vitest configured with TanStack Router plugin
  • Existing tests updated to use new utilities

Integrations

  • Sentry integration configured (if used)
  • nuqs adapter wrapped in root layout (if used)

Cleanup (after full migration)

  • React Router dependencies removed
  • Legacy route definitions deleted
  • BrowserRouter wrapper removed
  • RouterSync component removed

Common Pitfalls

  1. Missing from parameter - Always specify from in hooks for type safety
  2. Forgetting fallback() wrapper - Optional search params need fallback(z.string().optional(), undefined)
  3. Trailing slash inconsistency - Configure trailingSlash: 'never' and be consistent
  4. Editing routeTree.gen.ts - Never edit; it's auto-generated on file changes
  5. Missing build plugin - Routes won't generate without the bundler plugin
  6. Async navigation warnings - navigate() returns Promise; use void navigate() or await it
  7. Using <Navigate> for section redirects - Use beforeLoad with throw redirect() instead to prevent navigation loops in embedded mode: beforeLoad: () => {throw redirect({to: '/section/$tab', params: {tab: 'default'}, replace: true});}
  8. Trailing slash in from parameter for index routes - Index routes (files named index.tsx) require trailing slash in from: // Index route: /topics/$topicName/index.tsx useParams({from: '/topics/$topicName/'}) // ✅ Correct (trailing slash) useParams({from: '/topics/$topicName'}) // ❌ Wrong
  9. Missing HistoryState extension - Extend HistoryState interface for typed navigation state (see Phase 3)

Documentation

平台分布

Gemini CLI

29.49%
按下载量换算147

Claude Code

23.92%
按下载量换算119

Cursor

17.28%
按下载量换算86

Antigravity

11.79%
按下载量换算59

OpenCode

7.79%
按下载量换算39

windsurf

3.38%
按下载量换算17

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

继续浏览同类 Skills