[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6EGAM60HFEFYVM47CFVYZ77":3,"skill-same:01M6EGAM60HFEFYVM47CFVYZ77":54},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":21,"linkOnly":22,"markdownContent":23,"markdownBody":23,"frontMatter":24,"refName":25,"commitSha":26,"skillDirectory":27,"forksCount":28,"repositoryHtmlUrl":29,"repositoryHomepageUrl":30,"ownerHtmlUrl":31,"ownerBlogUrl":6,"ownerDescription":32,"updatedAt":33,"install":34,"resources":47},"01M6EGAM60HFEFYVM47CFVYZ77","tanstack-router",null,"ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",67,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002FTerminalSkills\u002Fskills\u002Ftanstack-router\u002FSKILL.md",[],[18,19,20],"tanstack","router","tanstack router","2026-11-10 10:12:30",false,"# TanStack Router\n\n## Overview\n\nTanStack Router is a fully type-safe router for React. Every route path, search param, path param, and loader is typed end-to-end — if you change a route, TypeScript catches every broken link at compile time. File-based routing with automatic code splitting, validated search params, and route-level data loading.\n\n## When to Use\n\n- React SPA or SSR app that needs type-safe routing (links, params, search)\n- Migrating from React Router and want compile-time route safety\n- Need validated and typed search\u002Fquery params (not just `string | undefined`)\n- Route-level data loading with pending\u002Ferror states\n- File-based routing with automatic code splitting\n\n## Instructions\n\n### Setup\n\n```bash\nnpm install @tanstack\u002Freact-router\nnpm install -D @tanstack\u002Frouter-plugin  # Vite plugin for file-based routing\n```\n\n```typescript\n\u002F\u002F vite.config.ts\nimport { defineConfig } from \"vite\";\nimport react from \"@vitejs\u002Fplugin-react\";\nimport { TanStackRouterVite } from \"@tanstack\u002Frouter-plugin\u002Fvite\";\n\nexport default defineConfig({\n  plugins: [TanStackRouterVite(), react()],\n});\n```\n\n### File-Based Routing\n\n```\nsrc\u002Froutes\u002F\n├── __root.tsx          # Root layout (wraps all pages)\n├── index.tsx           # \u002F\n├── about.tsx           # \u002Fabout\n├── users\u002F\n│   ├── index.tsx       # \u002Fusers\n│   ├── $userId.tsx     # \u002Fusers\u002F:userId (dynamic param)\n│   └── $userId\u002F\n│       └── posts.tsx   # \u002Fusers\u002F:userId\u002Fposts (nested)\n└── settings\u002F\n    ├── _layout.tsx     # Layout wrapper for \u002Fsettings\u002F*\n    ├── profile.tsx     # \u002Fsettings\u002Fprofile\n    └── billing.tsx     # \u002Fsettings\u002Fbilling\n```\n\n### Root Layout\n\n```tsx\n\u002F\u002F src\u002Froutes\u002F__root.tsx\nimport { createRootRoute, Outlet, Link } from \"@tanstack\u002Freact-router\";\n\nexport const Route = createRootRoute({\n  component: () => (\n    \u003Cdiv>\n      \u003Cnav className=\"flex gap-4 p-4 border-b\">\n        \u003CLink to=\"\u002F\" className=\"[&.active]:font-bold\">Home\u003C\u002FLink>\n        \u003CLink to=\"\u002Fusers\" className=\"[&.active]:font-bold\">Users\u003C\u002FLink>\n        \u003CLink to=\"\u002Fabout\" className=\"[&.active]:font-bold\">About\u003C\u002FLink>\n      \u003C\u002Fnav>\n      \u003Cmain className=\"p-4\">\n        \u003COutlet \u002F>\n      \u003C\u002Fmain>\n    \u003C\u002Fdiv>\n  ),\n});\n```\n\n### Route with Loader\n\n```tsx\n\u002F\u002F src\u002Froutes\u002Fusers\u002Findex.tsx — Route with data loading\nimport { createFileRoute } from \"@tanstack\u002Freact-router\";\nimport { z } from \"zod\";\n\n\u002F\u002F Search params schema — validated and typed\nconst usersSearchSchema = z.object({\n  page: z.number().int().positive().catch(1),\n  search: z.string().optional(),\n  role: z.enum([\"all\", \"admin\", \"user\"]).catch(\"all\"),\n});\n\nexport const Route = createFileRoute(\"\u002Fusers\u002F\")({\n  \u002F\u002F Validate search params with Zod\n  validateSearch: usersSearchSchema,\n\n  \u002F\u002F Load data before rendering (with typed search params)\n  loaderDeps: ({ search }) => ({ search }),\n  loader: async ({ deps: { search } }) => {\n    const params = new URLSearchParams({\n      page: String(search.page),\n      ...(search.search && { search: search.search }),\n      ...(search.role !== \"all\" && { role: search.role }),\n    });\n    const res = await fetch(`\u002Fapi\u002Fusers?${params}`);\n    return res.json() as Promise\u003C{ users: User[]; total: number }>;\n  },\n\n  component: UsersPage,\n});\n\nfunction UsersPage() {\n  const { users, total } = Route.useLoaderData();\n  const { page, search, role } = Route.useSearch();\n  const navigate = Route.useNavigate();\n\n  return (\n    \u003Cdiv>\n      \u003Ch1>Users ({total})\u003C\u002Fh1>\n\n      \u003Cinput\n        value={search ?? \"\"}\n        onChange={(e) => navigate({ search: { search: e.target.value, page: 1 } })}\n        placeholder=\"Search users...\"\n      \u002F>\n\n      \u003Cselect\n        value={role}\n        onChange={(e) => navigate({ search: { role: e.target.value as any, page: 1 } })}\n      >\n        \u003Coption value=\"all\">All roles\u003C\u002Foption>\n        \u003Coption value=\"admin\">Admin\u003C\u002Foption>\n        \u003Coption value=\"user\">User\u003C\u002Foption>\n      \u003C\u002Fselect>\n\n      {users.map((user) => (\n        \u003CLink key={user.id} to=\"\u002Fusers\u002F$userId\" params={{ userId: user.id }}>\n          {user.name}\n        \u003C\u002FLink>\n      ))}\n\n      \u003Cbutton\n        disabled={page \u003C= 1}\n        onClick={() => navigate({ search: { page: page - 1 } })}\n      >\n        Previous\n      \u003C\u002Fbutton>\n      \u003Cbutton onClick={() => navigate({ search: { page: page + 1 } })}>\n        Next\n      \u003C\u002Fbutton>\n    \u003C\u002Fdiv>\n  );\n}\n```\n\n### Dynamic Route Params\n\n```tsx\n\u002F\u002F src\u002Froutes\u002Fusers\u002F$userId.tsx — Dynamic route with typed params\nimport { createFileRoute, notFound } from \"@tanstack\u002Freact-router\";\n\nexport const Route = createFileRoute(\"\u002Fusers\u002F$userId\")({\n  loader: async ({ params: { userId } }) => {\n    \u002F\u002F userId is typed as string — no casting needed\n    const res = await fetch(`\u002Fapi\u002Fusers\u002F${userId}`);\n    if (!res.ok) throw notFound();\n    return res.json() as Promise\u003CUser>;\n  },\n\n  notFoundComponent: () => \u003Cdiv>User not found\u003C\u002Fdiv>,\n\n  component: UserProfile,\n});\n\nfunction UserProfile() {\n  const user = Route.useLoaderData();\n  \u002F\u002F    ^? User — fully typed from loader return\n\n  return (\n    \u003Cdiv>\n      \u003Ch1>{user.name}\u003C\u002Fh1>\n      \u003Cp>{user.email}\u003C\u002Fp>\n      \u003CLink to=\"\u002Fusers\u002F$userId\u002Fposts\" params={{ userId: user.id }}>\n        View Posts\n      \u003C\u002FLink>\n    \u003C\u002Fdiv>\n  );\n}\n```\n\n### Type-Safe Links\n\n```tsx\n\u002F\u002F Links are fully typed — wrong routes or missing params = compile error\nimport { Link } from \"@tanstack\u002Freact-router\";\n\n\u002F\u002F ✅ Correct — route exists, params match\n\u003CLink to=\"\u002Fusers\u002F$userId\" params={{ userId: \"123\" }}>Profile\u003C\u002FLink>\n\n\u002F\u002F ✅ Search params typed\n\u003CLink to=\"\u002Fusers\" search={{ page: 2, role: \"admin\" }}>Admin Users\u003C\u002FLink>\n\n\u002F\u002F ❌ Compile error — route doesn't exist\n\u003CLink to=\"\u002Fnonexistent\">Broken\u003C\u002FLink>\n\n\u002F\u002F ❌ Compile error — missing required param\n\u003CLink to=\"\u002Fusers\u002F$userId\">Missing userId\u003C\u002FLink>\n```\n\n## Examples\n\n### Example 1: Dashboard with filtered data views\n\n**User prompt:** \"Build a dashboard with users list that supports search, pagination, and role filtering — all in the URL.\"\n\nThe agent will set up TanStack Router with validated search params (page, search, role), route-level loader that fetches filtered data, and type-safe navigation that preserves filter state in the URL.\n\n### Example 2: Nested layouts for settings\n\n**User prompt:** \"Create a settings page with sidebar navigation — profile, billing, and team sections.\"\n\nThe agent will create a settings layout route with sidebar Links, nested routes for each section, and loaders for settings data.\n\n## Guidelines\n\n- **Search params = state** — use URL search params instead of React state for filterable\u002Fbookmarkable views\n- **Validate search params with Zod** — `.catch()` provides defaults for invalid params\n- **Loaders run before render** — no loading spinners for route-level data\n- **`notFound()` in loaders** — throw it to render the notFoundComponent\n- **Links are type-checked** — changing a route path catches all broken links at compile time\n- **File naming = route structure** — `$param` for dynamic segments, `_layout` for layout routes\n- **Code splitting is automatic** — each route file becomes a separate chunk\n- **`loaderDeps` controls re-fetching** — loader re-runs only when deps change\n- **TanStack Router + TanStack Query** — use together for server state + route state\n",{},"main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002FTerminalSkills\u002Fskills\u002Ftanstack-router",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":7,"skillName":5,"commands":35,"prompt":45,"zipAvailable":46},[36,39,42],{"tool":37,"command":38},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill tanstack-router",{"tool":40,"command":41},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill tanstack-router",{"tool":43,"command":44},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill tanstack-router","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002FTerminalSkills\u002Fskills\u002Ftanstack-router\u002FSKILL.md",true,[48],{"path":49,"resourceType":50,"resourceTypeDesc":51,"sizeBytes":52,"sourceHtmlUrl":53},"DESIGN.md","REFERENCE","参考文档",1558,"https:\u002F\u002Fgithub.com\u002FTorchiaHub\u002FSkills\u002Fblob\u002Fmaster\u002F01-Inbox\u002Fdownloads\u002Fbergside-design-skills\u002F20260516T145411Z\u002Fsource\u002Fskills\u002Fagentic\u002FDESIGN.md",[55,69,79,88,94,101],{"skillNo":56,"name":57,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":58,"categories":59,"keywords":65,"publishedAt":21},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[60],{"categoryNo":61,"categoryName":62,"taxonomyType":63,"taxonomyTypeDesc":64},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[66,67,68],"model","model hierarchy","model hierarchy skill",{"skillNo":70,"name":71,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":72,"categories":73,"keywords":75,"publishedAt":21},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[74],{"categoryNo":61,"categoryName":62,"taxonomyType":63,"taxonomyTypeDesc":64},[76,77,78],"MCP","zoom","zoom mcp",{"skillNo":80,"name":81,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":82,"categories":83,"keywords":84,"publishedAt":21},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[85,86,87,77],"sdk","zoom apps sdk","apps",{"skillNo":89,"name":90,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":91,"categories":92,"keywords":93,"publishedAt":21},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[90],{"skillNo":95,"name":96,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":97,"categories":98,"keywords":100,"publishedAt":21},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[99],{"categoryNo":61,"categoryName":62,"taxonomyType":63,"taxonomyTypeDesc":64},[96],{"skillNo":102,"name":103,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":104,"categories":105,"keywords":106,"publishedAt":21},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[103]]