Agent SkillsTangleML/tangle-ui › tanstack-router

tanstack-router

GitHub

提供 TanStack Router v1 的路由定义、导航、搜索参数及数据获取的最佳实践模式,指导前端开发中代码路由配置与 URL 状态管理。

.claude/skills/tanstack-router/SKILL.md TangleML/tangle-ui

Trigger Scenarios

创建或修改前端路由 实现页面跳转逻辑 处理 URL 查询参数

Install

npx skills add TangleML/tangle-ui --skill tanstack-router -g -y
More Options

Non-standard path

npx skills add https://github.com/TangleML/tangle-ui/tree/master/.claude/skills/tanstack-router -g -y

Use without installing

npx skills use TangleML/tangle-ui@tanstack-router

指定 Agent (Claude Code)

npx skills add TangleML/tangle-ui --skill tanstack-router -a claude-code -g -y

安装 repo 全部 skill

npx skills add TangleML/tangle-ui --all -g -y

预览 repo 内 skill

npx skills add TangleML/tangle-ui --list

SKILL.md

Frontmatter
{
    "name": "tanstack-router",
    "description": "TanStack Router patterns for routing, navigation, search params, and layouts. Use when creating routes, navigating, or working with URL state."
}

TanStack Router Patterns

This project uses code-based routing (not file-based) with TanStack Router v1.

Route Definitions

All routes are defined in src/routes/router.ts using createRoute and assembled into a tree with addChildren:

const mainLayout = createRoute({
  id: "main-layout",
  getParentRoute: () => rootRoute,
  component: RootLayout,
});

const indexRoute = createRoute({
  getParentRoute: () => mainLayout,
  path: APP_ROUTES.HOME,
  component: Editor,
});

const appRouteTree = mainLayout.addChildren([
  indexRoute,
  quickStartRoute,
  settingsRouteTree,
  editorRoute,
]);

Route Path Constants

Use the APP_ROUTES constant object for all route paths — never hardcode path strings:

export const APP_ROUTES = {
  HOME: "/",
  QUICK_START: "/quick-start",
  PIPELINE_EDITOR: `${EDITOR_PATH}/$name`,
  RUN_DETAIL: `${RUNS_BASE_PATH}/$id`,
  RUNS: RUNS_BASE_PATH,
  SETTINGS: "/settings",
} as const;

Navigation

useNavigate hook:

const navigate = useNavigate();
navigate({ to: `${APP_ROUTES.RUNS}/${runId}` });

Handle Ctrl/Cmd+Click for new tabs:

const handleRowClick = (e: MouseEvent<HTMLElement>) => {
  if (e.ctrlKey || e.metaKey) {
    window.open(clickThroughUrl, "_blank");
    return;
  }
  navigate({ to: clickThroughUrl });
};

Link component with active state:

import { Link } from "@tanstack/react-router";

<Link
  to={item.to}
  replace
  activeProps={{ className: "is-active" }}
>
  {({ isActive }) => (
    <Button variant="ghost" className={cn("w-full", isActive && "bg-accent")}>
      <Icon name={item.icon} size="sm" />
      <Text size="sm">{item.label}</Text>
    </Button>
  )}
</Link>

Data Fetching

This project uses TanStack Query for data fetching, not route loaders. Routes do not define loader functions — use query hooks in components instead.

beforeLoad is only used for redirects and simple param extraction:

const settingsIndexRoute = createRoute({
  getParentRoute: () => settingsLayoutRoute,
  path: "/",
  beforeLoad: () => {
    throw redirect({ to: APP_ROUTES.SETTINGS_BACKEND });
  },
});

Search Params

Use useSearch with type casting and manual validation (not Zod):

type RunSectionSearch = { page_token?: string; filter?: string };
const search = useSearch({ strict: false }) as RunSectionSearch;
const filters = parseFilterParam(search.filter);

For complex search param management, see the useRunSearchParams hook in src/hooks/useRunSearchParams.ts which provides setFilter, clearFilters, hasActiveFilters, etc.

Validate search params with type guards, not Zod:

function isValidAnnotationFilter(value: unknown): value is AnnotationFilter {
  return (
    isRecord(value) &&
    typeof value.key === "string" &&
    (value.value === undefined || typeof value.value === "string")
  );
}

Route Params

const { id, subgraphExecutionId } = useParams();

Router Hooks

Hook Use Case
useNavigate() Programmatic navigation
useParams() Route parameters ($id, $name)
useSearch({ strict: false }) Search/query params
useLocation() Current pathname
useRouter() Router instance (history, back navigation)
useRouterState() Advanced state (resolved location, pending state)

Layout Nesting

Layouts use <Outlet /> for child routes. The root layout (RootLayout) wraps providers:

rootRoute
├── mainLayout (RootLayout: BackendProvider > ComponentSpecProvider > AppMenu + Outlet)
│   ├── indexRoute
│   ├── settingsLayoutRoute (SettingsLayout: sidebar + Outlet)
│   │   ├── settingsBackendRoute
│   │   └── secretsRouteTree
│   ├── editorRoute
│   └── runDetailRoute
└── Auth callback routes (no layout)

Router Config

export const router = createRouter({
  routeTree: rootRouteTree,
  defaultPreload: "intent",
  scrollRestoration: true,
  history,
  basepath: IS_GITHUB_PAGES ? "" : basepath,
});
  • defaultPreload: "intent" — preloads routes on hover/focus
  • scrollRestoration: true — restores scroll position on back navigation

Version History

  • d7768e8 Current 2026-09-02 20:59

Same Skill Collection

.claude/skills/accessibility/SKILL.md
.claude/skills/address-pr-comments/SKILL.md
.claude/skills/analytics-tracking/SKILL.md
.claude/skills/audit-tickets/SKILL.md
.claude/skills/docs-update/SKILL.md
.claude/skills/e2e-testing/SKILL.md
.claude/skills/list-skills/SKILL.md
.claude/skills/open-source/SKILL.md
.claude/skills/project-conventions/SKILL.md
.claude/skills/react-patterns/SKILL.md
.claude/skills/review/SKILL.md
.claude/skills/tangle-domain/SKILL.md
.claude/skills/tanstack-query/SKILL.md
.claude/skills/typescript-standards/SKILL.md
.claude/skills/ui-primitives/SKILL.md
.claude/skills/validate/SKILL.md
.claude/skills/vitest-testing/SKILL.md
.cursor/skills/playwright-testing/SKILL.md
public/agent-skills/componentYamlFormat/SKILL.md
public/agent-skills/tangleBestPractices/SKILL.md
.claude/skills/gardening/SKILL.md

Metadata

Files
0
Version
d7768e8
Hash
d473c4ea
Indexed
2026-09-02 20:59

trang chủ - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-09-03 02:21
浙ICP备14020137号-1 $bản đồ khách truy cập$