Skip to content

feat: add @tanstack/intent AI agent skills for Router and Start#6866

Open
tannerlinsley wants to merge 2 commits intomainfrom
feat/tanstack-intent-skills
Open

feat: add @tanstack/intent AI agent skills for Router and Start#6866
tannerlinsley wants to merge 2 commits intomainfrom
feat/tanstack-intent-skills

Conversation

@tannerlinsley
Copy link
Member

@tannerlinsley tannerlinsley commented Mar 8, 2026

Summary

Adds @tanstack/intent SKILL.md files across 11 packages to help AI coding agents (Claude, Cursor, Copilot, etc.) generate correct TanStack Router and Start code. Each skill covers patterns, API usage, and common failure modes that agents frequently get wrong.

What's included

28 SKILL.md files across 11 packages:

Package Skills Coverage
router-core 10 Core concepts, search/path params, navigation, data loading, auth/guards, code splitting, not-found/errors, type safety, SSR
react-router 3 React bindings, Router+Query composition, migration from React Router
start-client-core 6 Start setup, server functions, middleware, execution model, server routes, deployment
react-start 2 React Start bindings, migration from Next.js
virtual-file-routes 1 Programmatic route tree building
router-plugin 1 Bundler plugin configuration
start-server-core 1 Server-side runtime
solid-router 1 Solid bindings
vue-router 1 Vue bindings
solid-start 1 Solid Start bindings
vue-start 1 Vue Start bindings

Per-package scaffolding:

  • bin/intent.js shim for npx intent discovery
  • skills/_artifacts/ metadata (domain_map.yaml, skill_spec.md, skill_tree.yaml)
  • @tanstack/intent devDependency
  • Package.json wired with files and bin entries

Root-level artifacts:

  • _artifacts/skill_tree.yaml — consolidated Router skill tree (13 skills)
  • _artifacts/start_skill_tree.yaml — consolidated Start skill tree (8 skills)
  • _artifacts/domain_map.yaml and _artifacts/start_domain_map.yaml — domain maps

Key design decisions:

  • Core/framework-agnostic skills live in core packages (router-core, start-client-core)
  • Framework-specific skills live in framework packages (react-router, solid-router, vue-router, etc.)
  • Every skill reinforces TanStack's own API patterns — agents confuse Router/Start with Next.js or React Router due to training data
  • All skills emphasize full type inference (never cast, never annotate inferred values)
  • All 28 skills pass @tanstack/intent validate (under 500 lines, correct frontmatter)

GitHub labels created: 28 skill:* labels for issue/PR categorization

Summary by CodeRabbit

  • New Features

    • Added an intent CLI command across multiple packages to surface skill docs and tooling guidance.
  • Documentation

    • Added extensive skill guides (routing, navigation, params, data loading, auth, SSR, code-splitting, type-safety, migrations, Start server/functions, adapters for React/Solid/Vue).
  • Chores

    • Added domain maps, skill specs and skill trees for automated docs.
    • Updated package manifests to publish skills and expose CLI entry points.

Add SKILL.md files across 11 packages to help AI coding agents generate
correct TanStack Router and Start code. Skills cover common patterns,
API usage, and failure modes that agents frequently get wrong.

Packages with skills:
- router-core (10 skills): core concepts, search/path params, navigation,
  data loading, auth/guards, code splitting, not-found/errors, type safety, SSR
- react-router (3): React bindings, Router+Query composition, migration from React Router
- start-client-core (6): Start setup, server functions, middleware,
  execution model, server routes, deployment
- react-start (2): React Start bindings, migration from Next.js
- virtual-file-routes (1): programmatic route tree building
- router-plugin (1): bundler plugin configuration
- start-server-core (1): server-side runtime
- solid-router (1): Solid bindings
- vue-router (1): Vue bindings
- solid-start (1): Solid Start bindings
- vue-start (1): Vue Start bindings

Each package includes bin/intent.js shim, _artifacts/ metadata, and
@tanstack/intent devDependency.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 8, 2026

📝 Walkthrough

Walkthrough

Adds extensive documentation and skill artifacts for TanStack Router and Start ecosystems, plus CLI bootstrap bin scripts and package.json updates across multiple packages to publish skills and expose an intent CLI entry.

Changes

Cohort / File(s) Summary
Router Core
packages/router-core/bin/intent.js, packages/router-core/package.json, packages/router-core/skills/_artifacts/*, packages/router-core/skills/router-core/*
Added intent CLI wrapper and package metadata; introduced domain_map, skill_spec, skill_tree artifacts and comprehensive SKILL.md docs for core router features (navigation, data-loading, params, SSR, type-safety, code-splitting, auth, errors).
React Router Bindings
packages/react-router/bin/intent.js, packages/react-router/package.json, _artifacts/domain_map.yaml, _artifacts/skill_spec.md, _artifacts/skill_tree.yaml, packages/react-router/skills/.../SKILL.md
Added intent CLI wrapper and package metadata; added domain/skill artifacts and SKILL docs including React bindings, migration guide from React Router, and TanStack Query integration patterns.
Router Plugin
packages/router-plugin/bin/intent.js, packages/router-plugin/package.json, packages/router-plugin/skills/_artifacts/*, packages/router-plugin/skills/router-plugin/SKILL.md
Added intent CLI wrapper and package metadata; added plugin domain/skill artifacts and docs describing bundler integration and configuration for Vite/Webpack/Rspack/esbuild.
Virtual File Routes
packages/virtual-file-routes/bin/intent.js, packages/virtual-file-routes/package.json, packages/virtual-file-routes/skills/_artifacts/*, packages/virtual-file-routes/skills/virtual-file-routes/SKILL.md
Added intent CLI wrapper and package metadata; added artifacts and SKILL.md describing programmatic route-tree helpers and virtual-route integration.
Start Core (client & server)
packages/start-client-core/bin/intent.js, packages/start-client-core/package.json, packages/start-client-core/skills/_artifacts/*, packages/start-client-core/skills/start-core/*, packages/start-server-core/bin/intent.js, packages/start-server-core/package.json, packages/start-server-core/skills/_artifacts/*, packages/start-server-core/skills/start-server-core/SKILL.md
Added intent CLI wrappers and package metadata; added domain/skill artifacts and extensive SKILL.md docs for Start core (server functions, middleware, execution model, server routes, deployment).
React Start
packages/react-start/bin/intent.js, packages/react-start/package.json, packages/react-start/skills/_artifacts/*, packages/react-start/skills/react-start/SKILL.md, packages/react-start/skills/lifecycle/migrate-from-nextjs/SKILL.md
Added intent CLI wrapper and package metadata; added artifacts and SKILL.md docs for React Start integration and migration guidance from Next.js.
Solid Router & Solid Start
packages/solid-router/bin/intent.js, packages/solid-router/package.json, packages/solid-router/skills/_artifacts/*, packages/solid-router/skills/solid-router/SKILL.md, packages/solid-start/bin/intent.js, packages/solid-start/package.json, packages/solid-start/skills/_artifacts/*, packages/solid-start/skills/solid-start/SKILL.md
Added intent CLI wrappers and package metadata; added artifacts and comprehensive Solid-specific SKILL.md docs for router and start bindings, failure modes, and migration patterns.
Vue Router & Vue Start
packages/vue-router/bin/intent.js, packages/vue-router/package.json, packages/vue-router/skills/_artifacts/*, packages/vue-router/skills/vue-router/SKILL.md, packages/vue-start/bin/intent.js, packages/vue-start/package.json, packages/vue-start/skills/_artifacts/*, packages/vue-start/skills/vue-start/SKILL.md
Added intent CLI wrappers and package metadata; added artifacts and Vue-specific SKILL.md docs for router and start bindings, SSR shell guidance, and common pitfalls.
Additional Packages with intent bins
packages/react-router/..., packages/router-core/..., packages/router-plugin/..., packages/virtual-file-routes/..., packages/solid-router/..., packages/solid-start/..., packages/start-client-core/..., packages/start-server-core/..., packages/virtual-file-routes/..., packages/vue-router/..., packages/vue-start/...
Added small bin scripts (bin/intent.js) across many packages and updated package.json files to include bin, devDependencies for @tanstack/intent, and publish skills/bin while excluding _artifacts.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

"I hopped through docs with whiskers bright,
New skills and maps to shed some light,
Bins and guides all lined in rows,
Routes and starts in tidy prose,
A rabbit cheers — go read, delight!" 🐇

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat: add @tanstack/intent AI agent skills for Router and Start' directly describes the main change: adding AI agent skills across multiple packages.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/tanstack-intent-skills

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud
Copy link

nx-cloud bot commented Mar 8, 2026

🤖 Nx Cloud AI Fix Eligible

An automatically generated fix could have helped fix failing tasks for this run, but Self-healing CI is disabled for this workspace. Visit workspace settings to enable it and get automatic fixes in future runs.

To disable these notifications, a workspace admin can disable them in workspace settings.


View your CI Pipeline Execution ↗ for commit ec661f4

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ❌ Failed 10m 26s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 2m 5s View ↗

☁️ Nx Cloud last updated this comment at 2026-03-09 21:34:47 UTC

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 17

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

🟡 Minor comments (28)
packages/router-core/skills/router-core/search-params/SKILL.md-26-28 (1)

26-28: ⚠️ Potential issue | 🟡 Minor

Fix the split blockquote.

The blank line between these two quoted warnings trips markdownlint MD028 and can make the docs check fail. Keep them in one contiguous blockquote or turn them into separate paragraphs.

📝 Proposed fix
 > **CRITICAL**: Use `fallback()` from `@tanstack/zod-adapter`, NOT zod's `.catch()`. Using `.catch()` makes the output type `unknown`, destroying type safety.
-
 > **CRITICAL**: Types are fully inferred. Never annotate the return of `useSearch()`.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/router-core/skills/router-core/search-params/SKILL.md` around lines
26 - 28, Remove the blank line splitting the two quoted warnings so they form a
single contiguous blockquote (or alternatively render each as its own
paragraph); specifically, merge the lines containing "**CRITICAL**: Use
`fallback()` from `@tanstack/zod-adapter`, NOT zod's `.catch()`." and
"**CRITICAL**: Types are fully inferred. Never annotate the return of
`useSearch()`." into one blockquote section to fix the MD028 markdownlint error.
packages/router-core/skills/router-core/not-found-and-errors/SKILL.md-23-23 (1)

23-23: ⚠️ Potential issue | 🟡 Minor

Remove blank line between blockquotes.

The blank line between the two blockquote sections violates markdownlint rule MD028. Either merge the blockquotes or remove the blank line for consistency.

📝 Proposed fix
 > **CRITICAL**: Do NOT use the deprecated `NotFoundRoute`. When present, `notFound()` and `notFoundComponent` will NOT work. Remove it and use `notFoundComponent` instead.
-
 > **CRITICAL**: `useLoaderData` may be undefined inside `notFoundComponent`. Use `useParams`, `useSearch`, or `useRouteContext` instead.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/router-core/skills/router-core/not-found-and-errors/SKILL.md` at
line 23, Remove the blank line between the two blockquote sections in SKILL.md
to satisfy markdownlint MD028; locate the two consecutive blockquote blocks (the
lines starting with ">") and either merge them into a single continuous
blockquote or delete the empty line between them so they appear as one
contiguous block.
packages/react-router/skills/lifecycle/migrate-from-react-router/SKILL.md-23-25 (1)

23-25: ⚠️ Potential issue | 🟡 Minor

Fix the markdownlint warnings in this new skill doc.

Line 24 triggers MD028 because the blockquote is split by a raw blank line, and Line 462 triggers MD040 because the fence has no language. Small issues, but they keep the doc lint output noisy.

Suggested doc tweak
 > **CRITICAL**: If your UI is blank after migration, open the console. Errors like "cannot use useNavigate outside of context" mean React Router imports remain alongside TanStack Router imports. Uninstall `react-router` to surface them as TypeScript errors.
-
+>
 > **CRITICAL**: TanStack Router uses `to` + `params` for navigation, NOT template literal paths. Never interpolate params into the `to` string.
-```
+```text
 React Router: /posts/:postId
 TanStack Router: /posts/$postId
</details>


Also applies to: 462-465

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @packages/react-router/skills/lifecycle/migrate-from-react-router/SKILL.md
around lines 23 - 25, The markdown has two lint issues: a blockquote split by a
raw blank line (MD028) and a fenced code block with no language (MD040) in the
SKILL.md content; fix by removing the stray blank line inside the blockquote so
the two CRITICAL lines remain contiguous, and add a language identifier (e.g.,
text) to the triple-backtick fence shown in the suggested example (also
update the same fence at the other occurrence referenced) so the linter stops
flagging MD028 and MD040.


</details>

</blockquote></details>
<details>
<summary>packages/react-router/skills/lifecycle/migrate-from-react-router/SKILL.md-388-395 (1)</summary><blockquote>

`388-395`: _⚠️ Potential issue_ | _🟡 Minor_

**Include `react-router-dom` in the cleanup search.**

Line 391 and Line 392 only catch `from 'react-router'`, so stale `react-router-dom` imports slip past this checklist step. `npx tsc --noEmit` later helps, but the search itself is incomplete.

<details>
<summary>Suggested doc tweak</summary>

```diff
- grep -r "from 'react-router" src/
- grep -r 'from "react-router' src/
+ grep -rE "from ['\"]react-router(-dom)?['\"]" src/
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react-router/skills/lifecycle/migrate-from-react-router/SKILL.md`
around lines 388 - 395, Update the cleanup checklist in SKILL.md so the search
for remaining imports also catches react-router-dom; modify the two grep
commands that currently search for "from 'react-router" / 'from "react-router'
(the lines containing those grep commands) to either add equivalent grep lines
for "react-router-dom" or broaden the pattern to match both packages, so stale
react-router-dom imports are flagged before running npx tsc --noEmit.
packages/react-router/skills/lifecycle/migrate-from-react-router/SKILL.md-199-201 (1)

199-201: ⚠️ Potential issue | 🟡 Minor

Fix the active-state styling example to match TanStack Router's activeProps API.

The description mentions "automatic active data attribute," but TanStack Router's Link component uses the activeProps prop to apply styles when a link is active—not automatic data attributes. The example className="[&.active]:font-bold" doesn't align with this API; it should be activeProps={{ className: 'font-bold' }} to properly demonstrate how to style active links in TanStack Router.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react-router/skills/lifecycle/migrate-from-react-router/SKILL.md`
around lines 199 - 201, The active-state styling example is incorrect: replace
the suggestion to use an automatic `active` data attribute and the
`className="[&.active]:font-bold"` example with TanStack Router's `activeProps`
API on the `Link` component (e.g., use `activeProps={{ className: 'font-bold'
}}`) and update the text to explain `activeProps` applies props when a link is
active; keep the existing notes that `to` is a route path pattern and `params`
are separate typed props but remove the mention of an automatic `active` data
attribute.
packages/react-router/skills/compositions/router-query/SKILL.md-87-112 (1)

87-112: ⚠️ Potential issue | 🟡 Minor

Add missing import for QueryClientProvider.

Line 102 uses QueryClientProvider but it's not included in the imports (lines 89-91). For consistency with other examples in this document (lines 37 and 160 show the import), and to prevent readers from copying incomplete code, add the import.

📦 Proposed fix
 // src/router.tsx
-import { QueryClient } from '@tanstack/react-query'
+import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
 import { createRouter } from '@tanstack/react-router'
 import { routeTree } from './routeTree.gen'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react-router/skills/compositions/router-query/SKILL.md` around lines
87 - 112, The file is missing the QueryClientProvider import used in
createAppRouter's Wrap component; add QueryClientProvider to the existing import
from '@tanstack/react-query' (alongside QueryClient) at the top of the file so
createAppRouter and its Wrap JSX can reference QueryClientProvider correctly.
packages/router-core/skills/router-core/search-params/references/validation-patterns.md-241-247 (1)

241-247: ⚠️ Potential issue | 🟡 Minor

Same issue: installation includes unused adapter.

Line 243 states "No adapter needed" but line 246 includes @tanstack/arktype-adapter in the installation. Unlike the Valibot section, there's no alternative example showing adapter usage here. Either remove the adapter from the installation command or add a section explaining when it's needed.

📝 Suggested fix
 ## ArkType (Standard Schema)
 
 ArkType 2.0-rc+ implements Standard Schema. No adapter needed — pass the type directly to `validateSearch`.
 
 ```bash
-npm install arktype `@tanstack/arktype-adapter`
+npm install arktype
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In
@packages/router-core/skills/router-core/search-params/references/validation-patterns.md
around lines 241 - 247, The install command incorrectly includes
@tanstack/arktype-adapter despite the preceding text saying "No adapter needed"
for ArkType 2.0-rc+; update the documentation in the ArkType (Standard Schema)
block by removing the adapter from the npm install line so it reads just "npm
install arktype", or alternatively keep the adapter but add a brief clarifying
sentence and example that explains when and why @tanstack/arktype-adapter is
required (mirroring the Valibot section) and show the adapter usage; update the
surrounding text to remain consistent with the chosen approach.


</details>

</blockquote></details>
<details>
<summary>packages/router-core/skills/router-core/search-params/references/validation-patterns.md-174-179 (1)</summary><blockquote>

`174-179`: _⚠️ Potential issue_ | _🟡 Minor_

**Clarify installation command vs. "no adapter needed" statement.**

Line 176 states "No adapter wrapper needed" but line 179 includes `@tanstack/valibot-adapter` in the installation command. Since the adapter is shown as an "Alternative" approach later (line 222), consider either:
- Moving the adapter installation to line 224 (near the alternative section), or  
- Adding a note explaining the adapter is optional for advanced use cases

This will reduce confusion about which packages users actually need.


<details>
<summary>📝 Suggested clarification</summary>

```diff
 ## Valibot (Standard Schema)
 
 Valibot 1.0+ implements Standard Schema. No adapter wrapper needed — pass the schema directly to `validateSearch`.
 
 ```bash
-npm install valibot `@tanstack/valibot-adapter`
+npm install valibot

Then in the alternative section:

```diff
 ### Valibot with Adapter (Alternative)
 
 If you need explicit input/output type control:
 
+```bash
+npm install `@tanstack/valibot-adapter`
+```
+
 ```tsx
 import { valibotValidator } from '@tanstack/valibot-adapter'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/router-core/skills/router-core/search-params/references/validation-patterns.md`
around lines 174 - 179, The docs currently say "No adapter wrapper needed" but
the install line includes `@tanstack/valibot-adapter` which contradicts that;
update the Valibot section so the primary install command installs only valibot
(for use with validateSearch) and either move the `@tanstack/valibot-adapter`
install into the "Alternative" section near the valibotValidator example or add
a one-line note that the adapter is optional for advanced use cases; ensure
references to validateSearch and valibotValidator remain unchanged so readers
can locate the usage examples.
packages/router-core/skills/router-core/navigation/SKILL.md-402-417 (1)

402-417: ⚠️ Potential issue | 🟡 Minor

Change the comment from "no accessibility" to "no link semantics."

Native <button> elements are accessible by default—they're focusable, keyboard-activable, and expose proper semantics to assistive technologies. The real issue here is that the button lacks link semantics and router affordances like href, Cmd/Ctrl+Click behavior, and active/inactive states. Calling it "no accessibility" teaches the wrong model and obscures why <Link> is the better choice.

Suggested wording
-// WRONG — no href, no cmd+click, no preloading, no accessibility
+// WRONG — no href, no cmd+click, no preloading, and no link semantics
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/router-core/skills/router-core/navigation/SKILL.md` around lines 402
- 417, Update the explanatory comment in the MEDIUM example to replace "no
accessibility" with "no link semantics" and explain that using useNavigate in
the BadNav example (function BadNav) results in a button element that lacks link
semantics and router affordances (no href, no Cmd/Ctrl-click, no preloading, no
active state), while the GoodNav example (function GoodNav using Link) preserves
those link semantics; edit the text around useNavigate/BadNav/GoodNav to reflect
this corrected phrasing and rationale.
packages/router-core/skills/router-core/navigation/SKILL.md-171-171 (1)

171-171: ⚠️ Potential issue | 🟡 Minor

Clarify freshness vs eviction here.

This sentence currently teaches the wrong knob: TanStack Router uses defaultPreloadStaleTime for how long preloaded data is considered fresh, while unused preloaded data is evicted based on defaultPreloadMaxAge. As written, an agent trying to change retention will likely edit the stale-time setting instead.

Suggested wording
-Preloaded data is cached for 30 seconds by default (`defaultPreloadStaleTime`). When using an external cache like TanStack Query, set `defaultPreloadStaleTime: 0` to let the external library control freshness.
+Preloaded data is considered fresh for 30 seconds by default (`defaultPreloadStaleTime`). Unused preloaded data is evicted after 30 seconds by default (`defaultPreloadMaxAge`). When using an external cache like TanStack Query, set `defaultPreloadStaleTime: 0` to let the external library control freshness.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/router-core/skills/router-core/navigation/SKILL.md` at line 171, The
docs confuse freshness vs eviction: update the sentence to state that
defaultPreloadStaleTime controls how long preloaded data is considered fresh,
while defaultPreloadMaxAge controls how long unused preloaded data is kept
(evicted after this age); mention that when delegating retention to an external
cache like TanStack Query you should set defaultPreloadMaxAge appropriately
(e.g., 0) if you want the external cache to control eviction, and set
defaultPreloadStaleTime to 0 only if you want the external library to control
freshness. Reference the symbols defaultPreloadStaleTime and
defaultPreloadMaxAge when making this change.
packages/router-core/skills/router-core/path-params/SKILL.md-277-287 (1)

277-287: ⚠️ Potential issue | 🟡 Minor

Add missing imports to code snippets using redirect and notFound.

Both examples read like full route files, but redirect and notFound are standalone exports from @tanstack/react-router that must be explicitly imported. Other skill files in the codebase consistently include these imports in similar examples. Omitting them makes it easy for developers to copy-paste non-compiling code.

✏️ Suggested doc fix
+import { createFileRoute, redirect } from '@tanstack/react-router'
+
 export const Route = createFileRoute('/posts/$postId')({
   beforeLoad: async ({ params }) => {
     // params.postId available here
     const canView = await checkPermission(params.postId)
     if (!canView) throw redirect({ to: '/unauthorized' })
   },
   loader: async ({ params }) => {
     return fetchPost(params.postId)
   },
 })
+import { createFileRoute, notFound } from '@tanstack/react-router'
+
 export const Route = createFileRoute('/posts/$postId')({
   loader: async ({ params }) => {
     const id = parseInt(params.postId, 10)
     if (isNaN(id)) throw notFound()
     return fetchPost(id)
   },
 })

Also applies to: 359-381

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/router-core/skills/router-core/path-params/SKILL.md` around lines
277 - 287, The example route snippets use the standalone exports redirect and
notFound but don't import them; update the Route examples using createFileRoute
(and related examples at the other location) to add an explicit import for
redirect and/or notFound from "@tanstack/react-router" so the beforeLoad, loader
and notFound usage compiles when copy-pasted—locate the examples referencing
redirect, notFound, Route, createFileRoute, beforeLoad and loader and add the
appropriate import statements.
packages/router-core/skills/router-core/path-params/SKILL.md-317-335 (1)

317-335: ⚠️ Potential issue | 🟡 Minor

Clarify route syntax vs. param key for splat routes.

The current section conflates $ (route syntax) with _splat (param access). While technically correct that $ is used for routes and _splat for params, the wording "The captured value is under _splat, not *" is misleading—* is a v1 backwards-compatibility alias, not an error. For AI skill documentation, explicitly separate the two concepts:

✏️ Suggested wording
-TanStack Router uses `$` for splat routes. The captured value is under `_splat`, not `*`.
+TanStack Router uses `$` in the route path for splat routes. The captured value is available under the `_splat` param key.
...
-> Note: `*` works in v1 for backwards compatibility but will be removed in v2. Always use `_splat`.
+> Note: Prefer `$` for route syntax and `_splat` for param access. The `*` key is a v1-only backwards-compatibility alias and will be removed in v2.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/router-core/skills/router-core/path-params/SKILL.md` around lines
317 - 335, Reword the paragraph in SKILL.md to separate route syntax from param
access: state that routes use `$` in path syntax (e.g., File:
src/routes/files.$.tsx) while the captured value is available as the `_splat`
param via Route.useParams(); clarify that `*` is only a v1
backwards-compatibility alias (not the param name) and will be removed in v2,
and update the example and wording to reflect that distinction (reference
symbols: createFileRoute, Route.useParams(), `_splat`, `$`, and `*`).
packages/virtual-file-routes/skills/_artifacts/skill_spec.md-9-15 (1)

9-15: ⚠️ Potential issue | 🟡 Minor

Domain name inconsistency between tables.

Line 9 uses "Virtual Route Configuration" (title case) while Line 15 uses "virtual-route-config" (hyphenated lowercase). Consider using a consistent format across both tables to avoid potential tooling mismatches.

Proposed fix
 | Skill               | Type | Domain               | What it covers                                             | Failure modes |
 | ------------------- | ---- | -------------------- | ---------------------------------------------------------- | ------------- |
-| virtual-file-routes | core | virtual-route-config | rootRoute, index, route, layout, physical, subtree configs | 2             |
+| virtual-file-routes | core | Virtual Route Configuration | rootRoute, index, route, layout, physical, subtree configs | 2             |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/virtual-file-routes/skills/_artifacts/skill_spec.md` around lines 9
- 15, The "Virtual Route Configuration" title in the first table and the
"virtual-route-config" domain cell in the Skill Inventory table are
inconsistent; update one so both use the same normalized format (pick either
Title Case or hyphenated-lowercase) — e.g., change "Virtual Route Configuration"
to "virtual-route-config" OR change the domain cell "virtual-route-config" to
"Virtual Route Configuration" — and ensure both occurrences (the table header
and the Domain column entry) match exactly.
packages/router-plugin/skills/_artifacts/skill_spec.md-9-15 (1)

9-15: ⚠️ Potential issue | 🟡 Minor

Domain name inconsistency between tables.

Line 9 uses "Bundler Integration" (title case) while Line 15 uses "bundler-integration" (hyphenated lowercase). This pattern appears across multiple skill_spec.md files in this PR—consider normalizing all domain references to a single format.

Proposed fix
 | Skill         | Type | Domain              | What it covers                                                 | Failure modes |
 | ------------- | ---- | ------------------- | -------------------------------------------------------------- | ------------- |
-| router-plugin | core | bundler-integration | Vite/Webpack/Rspack/esbuild plugins, route gen, code splitting | 2             |
+| router-plugin | core | Bundler Integration | Vite/Webpack/Rspack/esbuild plugins, route gen, code splitting | 2             |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/router-plugin/skills/_artifacts/skill_spec.md` around lines 9 - 15,
The domain string is inconsistent: change the header cell "Bundler Integration"
in the first table to match the inventory format "bundler-integration" so both
table entries use the same lowercase hyphenated form; update the header in the
top table (the cell under the first table's second column) to
"bundler-integration" and scan other skill_spec.md files to normalize any other
occurrences to this same format (e.g., ensure the "router-plugin" row's Domain
value remains "bundler-integration").
packages/vue-router/skills/_artifacts/skill_spec.md-9-15 (1)

9-15: ⚠️ Potential issue | 🟡 Minor

Domain name inconsistency between tables.

Line 9 uses "Vue Router Bindings" (title case with spaces) while Line 15 uses "vue-router-bindings" (hyphenated lowercase). If the intent tooling performs case-sensitive domain matching, this mismatch could cause lookup failures.

Proposed fix
 | Skill      | Type      | Domain              | What it covers                                                  | Failure modes |
 | ---------- | --------- | ------------------- | --------------------------------------------------------------- | ------------- |
-| vue-router | framework | vue-router-bindings | Ref<T> returns, defineComponent, h(), provide/inject, Html/Body | 2             |
+| vue-router | framework | Vue Router Bindings | Ref<T> returns, defineComponent, h(), provide/inject, Html/Body | 2             |

Or normalize to the hyphenated form in both tables, depending on the convention used by @tanstack/intent.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/vue-router/skills/_artifacts/skill_spec.md` around lines 9 - 15, The
domain string is inconsistent between the top table title "Vue Router Bindings"
and the Skill Inventory domain value "vue-router-bindings"; normalize them to
the same form (prefer the hyphenated lowercase convention used by
`@tanstack/intent`) by changing the title or the domain value so both read
"vue-router-bindings" and ensure the domain column for the "vue-router" skill
and the table header use that exact string.
packages/router-plugin/bin/intent.js-8-19 (1)

8-19: ⚠️ Potential issue | 🟡 Minor

Disambiguate transitive dependency failures from missing @tanstack/intent.

The catch block at lines 8–19 treats any ERR_MODULE_NOT_FOUND or MODULE_NOT_FOUND as "@tanstack/intent is not installed," but Node.js throws these errors for any unresolved module during import—including missing transitive dependencies or broken internal modules within @tanstack/intent. This masks the actual problem: a broken install or incompatible version.

Check the error message for @tanstack/intent to distinguish the two cases. Only show the friendly install hint when the missing package is @tanstack/intent itself; rethrow other resolution failures unchanged.

Proposed fix
 try {
   await import('@tanstack/intent/intent-library')
 } catch (e) {
-  if (e?.code === 'ERR_MODULE_NOT_FOUND' || e?.code === 'MODULE_NOT_FOUND') {
+  const code = e && typeof e === 'object' ? e.code : undefined
+  const message = e instanceof Error ? e.message : String(e)
+  const isMissingIntent =
+    (code === 'ERR_MODULE_NOT_FOUND' || code === 'MODULE_NOT_FOUND') &&
+    /@tanstack\/intent(\/intent-library)?/.test(message)
+
+  if (isMissingIntent) {
     console.error('@tanstack/intent is not installed.')
     console.error('')
     console.error('Install it as a dev dependency:')
     console.error('  npm add -D `@tanstack/intent`')
     console.error('')

Note: This pattern appears in 12 files across the repository and should be updated consistently.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/router-plugin/bin/intent.js` around lines 8 - 19, The catch block in
packages/router-plugin/bin/intent.js currently treats any
ERR_MODULE_NOT_FOUND/MODULE_NOT_FOUND as “@tanstack/intent is not installed”;
change it to inspect the error text to ensure the missing module is actually
'@tanstack/intent' before showing the friendly install hint: check e.message (or
e?.stack) for the exact string "Cannot find module" or the module name
"'@tanstack/intent'" (or "@tanstack/intent") and only print the install/help
output in that case; for all other ERR_MODULE_NOT_FOUND/MODULE_NOT_FOUND errors
rethrow e unchanged so transitive dependency or internal module failures are not
masked. Apply the same check pattern to other similar catch blocks found across
the repo.
packages/start-client-core/bin/intent.js-8-19 (1)

8-19: ⚠️ Potential issue | 🟡 Minor

Don't treat every MODULE_NOT_FOUND as "intent is missing".

This catch block only checks e.code. If @tanstack/intent/intent-library is present but one of its imports is missing, the shim will print the install hint and exit with a misleading error message. Narrow the guard to errors that specifically mention @tanstack/intent/intent-library in the error message before applying the fallback message.

♻️ Suggested guard
 } catch (e) {
-  if (e?.code === 'ERR_MODULE_NOT_FOUND' || e?.code === 'MODULE_NOT_FOUND') {
+  const isMissingIntentLibrary =
+    (e?.code === 'ERR_MODULE_NOT_FOUND' || e?.code === 'MODULE_NOT_FOUND') &&
+    String(e?.message ?? '').includes('@tanstack/intent/intent-library')
+
+  if (isMissingIntentLibrary) {
     console.error('@tanstack/intent is not installed.')
     console.error('')
     console.error('Install it as a dev dependency:')
@@
     process.exit(1)
   }
   throw e
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/start-client-core/bin/intent.js` around lines 8 - 19, The catch
block currently treats any ERR_MODULE_NOT_FOUND/MODULE_NOT_FOUND as if
`@tanstack/intent` is missing; update the guard in the catch to also verify the
error message references the specific module path (e.g.
'@tanstack/intent/intent-library') before printing the install hint and
exiting—keep the existing e.code checks (e?.code === 'ERR_MODULE_NOT_FOUND' ||
e?.code === 'MODULE_NOT_FOUND') but require e.message (or e.toString()) to
include the module identifier string before running the console.error/install
instructions in the same catch block.
packages/start-server-core/package.json-89-98 (1)

89-98: ⚠️ Potential issue | 🟡 Minor

Consider making the npx fallback automatic or moving @tanstack/intent to dependencies.

When ./bin/intent.js is called by a consumer without @tanstack/intent installed, it fails gracefully with error messaging that suggests running npx @tanstack/intent@latest. However, this requires user intervention. If the binary should work seamlessly for consumers of this package, either:

  • Move @tanstack/intent from devDependencies to dependencies, or
  • Automatically invoke the npx fallback instead of just suggesting it.

The current error handling is present but reactive rather than proactive.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/start-server-core/package.json` around lines 89 - 98, The package
currently lists "@tanstack/intent" under devDependencies but exposes a bin
"intent" that requires it; update package.json to move "@tanstack/intent" from
devDependencies into dependencies so consumers get it installed, or
alternatively modify the runtime in ./bin/intent.js (the "intent" entry point)
to programmatically attempt to require("@tanstack/intent") and, on failure,
spawn an automatic "npx `@tanstack/intent`@latest" fallback instead of only
printing instructions; pick one approach, ensure the change references the
"@tanstack/intent" dependency and the "./bin/intent.js" bin entry, and update
package.json accordingly.
packages/virtual-file-routes/skills/virtual-file-routes/SKILL.md-214-219 (1)

214-219: ⚠️ Potential issue | 🟡 Minor

The documentation comment is contradictory and should be clarified.

Lines 215 and 218 contradict each other: line 215 says "does NOT create a /dashboard URL" while line 218 says "The URL is /dashboard". The intended point—that layout() contributes no path segment—gets lost. Update to clarify that layout() itself is pathless while the child route provides the segment:

Suggested fix
-// This does NOT create a /dashboard URL
+// `layout()` itself does not add a URL segment
 layout('dashboardLayout.tsx', [route('/dashboard', 'dashboard.tsx')])

-// The URL is /dashboard, and dashboardLayout.tsx wraps it
+// `/dashboard` comes from the child route; the layout only wraps it
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/virtual-file-routes/skills/virtual-file-routes/SKILL.md` around
lines 214 - 219, The comment is contradictory about whether
layout('dashboardLayout.tsx', [route('/dashboard', 'dashboard.tsx')]) creates
the /dashboard path; update the doc to state clearly that layout() is pathless
and does not add a URL segment, while the child route(route('/dashboard',
'dashboard.tsx')) supplies the /dashboard path and is wrapped by
dashboardLayout.tsx. Mention the symbols layout(), route(), dashboardLayout.tsx
and dashboard.tsx so readers can find the example.
packages/start-client-core/skills/start-core/middleware/SKILL.md-23-25 (1)

23-25: ⚠️ Potential issue | 🟡 Minor

Remove the blank line inside the CRITICAL blockquote.

The empty line here trips markdownlint MD028.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/start-client-core/skills/start-core/middleware/SKILL.md` around
lines 23 - 25, Remove the empty line inside the CRITICAL blockquote in SKILL.md
so the two CRITICAL sentences about method order (`middleware()` →
`inputValidator()` → `client()` → `server()`) and `sendContext` validation
appear as a single continuous blockquote paragraph; edit the blockquote to join
the sentences without a blank line to satisfy markdownlint MD028.
packages/react-router/skills/react-router/SKILL.md-29-33 (1)

29-33: ⚠️ Potential issue | 🟡 Minor

Keep the CRITICAL callouts in one blockquote.

The blank lines on Line 30 and Line 32 trigger markdownlint MD028.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react-router/skills/react-router/SKILL.md` around lines 29 - 33,
Combine the three separate CRITICAL blockquotes into a single blockquote by
merging the three lines starting with "**CRITICAL**: TanStack Router types...",
"**CRITICAL**: TanStack Router is CLIENT-FIRST...", and "**CRITICAL**: Do not
confuse `@tanstack/react-router`..." into one contiguous blockquote with no
blank lines between them to satisfy markdownlint MD028 (remove the blank lines
that currently exist between those CRITICAL callouts).
packages/start-client-core/skills/start-core/execution-model/SKILL.md-23-27 (1)

23-27: ⚠️ Potential issue | 🟡 Minor

Remove the blank lines inside the CRITICAL blockquote.

The empty lines between these three callouts trip markdownlint MD028.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/start-client-core/skills/start-core/execution-model/SKILL.md` around
lines 23 - 27, Remove the empty lines inside the CRITICAL blockquote in SKILL.md
so the three bullet sentences are contiguous (no blank lines between the three
lines beginning with "**CRITICAL**: ALL code...", "**CRITICAL**: Module-level
`process.env`...", and "**CRITICAL**: `VITE_` prefixed..."). Edit the blockquote
so it reads as three consecutive lines with no blank lines to satisfy
markdownlint MD028.
packages/react-start/skills/_artifacts/skill_tree.yaml-11-12 (1)

11-12: ⚠️ Potential issue | 🟡 Minor

Path resolution for generated_from reference needs clarification.

The generated_from references _artifacts/start_domain_map.yaml. The actual file exists at the repository root (_artifacts/start_domain_map.yaml), but the YAML file is located in packages/react-start/skills/_artifacts/. If the consuming tool resolves paths relative to the YAML file's location, the reference will fail. Confirm whether paths are resolved from the repository root or relative to the file's directory, and adjust the path accordingly if needed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react-start/skills/_artifacts/skill_tree.yaml` around lines 11 - 12,
The generated_from reference in skill_tree.yaml points to start_domain_map.yaml
but may be resolved relative to the YAML file instead of the repository root;
check how the consuming tool resolves paths, and then update the generated_from
value in skill_tree.yaml so it correctly points to start_domain_map.yaml (either
by changing it to a repo-root absolute reference or by rewriting it as the
correct relative path from the skill_tree.yaml location) so the resolver finds
the start_domain_map.yaml file.
packages/solid-router/skills/solid-router/SKILL.md-27-33 (1)

27-33: ⚠️ Potential issue | 🟡 Minor

Remove the blank lines inside this blockquote.

markdownlint already flags MD028 here, so this doc will ship with avoidable warnings.

🧹 Proposed fix
 > **CRITICAL**: TanStack Router types are FULLY INFERRED. Never cast, never annotate inferred values.
-
 > **CRITICAL**: TanStack Router is CLIENT-FIRST. Loaders run on the client by default, not on the server.
-
 > **CRITICAL**: Most hooks return `Accessor<T>` — you MUST call the accessor (`value()`) to read the reactive value. This is the `#1` difference from the React version.
-
 > **CRITICAL**: Do not confuse `@tanstack/solid-router` with `@solidjs/router`. They are completely different libraries with different APIs.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/solid-router/skills/solid-router/SKILL.md` around lines 27 - 33, The
blockquote containing the four "**CRITICAL**" lines currently has empty blank
lines inside it which triggers markdownlint MD028; remove the extra blank lines
so the blockquote is a contiguous set of lines (ensure each line begins with ">"
and there are no empty ">" lines between them), preserving the exact text of the
"**CRITICAL**" entries (e.g., the lines starting with "> **CRITICAL**: TanStack
Router types...", "> **CRITICAL**: TanStack Router is CLIENT-FIRST...", ">
**CRITICAL**: Most hooks return `Accessor<T>`...", "> **CRITICAL**: Do not
confuse `@tanstack/solid-router`...") to resolve the lint warning.
packages/router-core/skills/router-core/auth-and-guards/SKILL.md-23-23 (1)

23-23: ⚠️ Potential issue | 🟡 Minor

Fix the relative link to the parent skill.

From packages/router-core/skills/router-core/auth-and-guards/, this target walks up one directory too many and resolves to a non-existent path. ../SKILL.md points at the sibling parent skill.

🔗 Proposed fix
-This skill builds on router-core. Read [router-core](../../../router-core/skills/router-core/SKILL.md) first for foundational concepts.
+This skill builds on router-core. Read [router-core](../SKILL.md) first for foundational concepts.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/router-core/skills/router-core/auth-and-guards/SKILL.md` at line 23,
Update the broken relative link in
packages/router-core/skills/router-core/auth-and-guards/SKILL.md so it points to
the parent skill one directory up; replace the incorrect ../../SKILL.md (which
climbs too many levels) with ../SKILL.md to reference the sibling parent skill
correctly.
packages/start-client-core/skills/start-core/server-routes/SKILL.md-254-263 (1)

254-263: ⚠️ Potential issue | 🟡 Minor

Add a language tag to the route-conflict example fence.

The fence opened at Line 256 is unlabeled, so it trips MD040 and loses syntax highlighting. text would be enough here.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/start-client-core/skills/start-core/server-routes/SKILL.md` around
lines 254 - 263, The code block in the "1. MEDIUM: Duplicate route paths"
example is an unlabeled fenced code block (the triple-backtick fence containing
"# WRONG — both resolve to /users, causes error" and the following lines), which
triggers MD040; add a language tag (e.g., change ``` to ```text) on that fence
so the example is labelled and gains correct syntax highlighting and linter
compliance.
packages/start-client-core/skills/start-core/server-functions/SKILL.md-22-24 (1)

22-24: ⚠️ Potential issue | 🟡 Minor

Fix the markdownlint warnings in this skill doc.

Line 23 still trips MD028 because the adjacent blockquotes are separated by a raw blank line, and the fence opened at Line 228 should be tagged as text/plaintext to satisfy MD040.

Also applies to: 228-233

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/start-client-core/skills/start-core/server-functions/SKILL.md`
around lines 22 - 24, Fix the markdownlint issues by removing the raw blank line
between the two adjacent blockquotes (the pair starting with "**CRITICAL**:
Loaders are ISOMORPHIC..." and the subsequent "**CRITICAL**: Do not use..."
block) so they are consecutive blockquote lines (resolves MD028), and update the
fenced code block near the bottom of SKILL.md (the fence opened as an untyped
triple-backtick block around the example text) to include an explicit language
tag of either "text" or "plaintext" (resolves MD040); ensure no other blank
lines separate those blockquotes and that the fence uses ```text or
```plaintext.
packages/start-client-core/skills/start-core/SKILL.md-21-25 (1)

21-25: ⚠️ Potential issue | 🟡 Minor

Fix the markdownlint warnings in the overview skill.

Lines 21-25 still have raw blank lines between adjacent blockquotes (MD028), and the decision tree opened at Line 39 should declare a language such as text so MD040 stays clean.

Also applies to: 39-54

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/start-client-core/skills/start-core/SKILL.md` around lines 21 - 25,
Fix the markdownlint issues: remove the raw blank lines between adjacent
blockquotes in the overview so the multiple consecutive > lines are contiguous
(address MD028) and add a language identifier (e.g., "text") to the fenced
decision-tree code block opened around the decision tree (the fenced block
starting near Line 39) to satisfy MD040; update the SKILL.md blockquote group
and the code fence declaration accordingly.
🧹 Nitpick comments (5)
packages/router-core/skills/router-core/type-safety/SKILL.md (1)

24-26: Optional: Address markdownlint warning for stricter compliance.

The blank line between blockquotes improves readability by separating two distinct critical warnings, but markdownlint flags this as MD028. If strict linter compliance is required, you can remove the blank line or merge the blockquotes.

🔧 Optional fix to merge blockquotes
 > **CRITICAL**: NEVER use `as Type`, explicit generic params, `satisfies` on hook returns, or type annotations on inferred values. Every cast masks real type errors and breaks the inference chain.
-
+>
 > **CRITICAL**: Do NOT confuse TanStack Router with Next.js or React Router. There is no `getServerSideProps`, no `useSearchParams()`, no `useLoaderData()` from `react-router-dom`.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/router-core/skills/router-core/type-safety/SKILL.md` around lines 24
- 26, The markdown contains two adjacent blockquotes that are separated by a
blank line which triggers markdownlint MD028; edit SKILL.md to either remove the
blank line between the two CRITICAL blockquotes or merge them into a single
blockquote so the warnings remain intact but the file passes the linter (target
the two lines containing the "**CRITICAL**:" messages and adjust spacing
accordingly).
packages/router-core/skills/router-core/data-loading/SKILL.md (1)

483-484: Consider using markdown links for cross-references.

The cross-references are formatted as bold text. If these SKILL.md files are meant to be navigable or if the skill system supports linking, consider using standard markdown link syntax for consistency:

-- See also: **router-core/search-params/SKILL.md** — `loaderDeps` consumes validated search params as cache keys
-- See also: **compositions/router-query/SKILL.md** — for external cache coordination with TanStack Query
+- See also: [router-core/search-params](../search-params/SKILL.md) — `loaderDeps` consumes validated search params as cache keys
+- See also: [compositions/router-query](../../../compositions/router-query/SKILL.md) — for external cache coordination with TanStack Query

Alternatively, if the bold text format is the standard convention for the @tanstack/intent skill system, this is fine as-is.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/router-core/skills/router-core/data-loading/SKILL.md` around lines
483 - 484, Replace the bold cross-reference lines that currently read
"**router-core/search-params/SKILL.md** — `loaderDeps` consumes validated search
params as cache keys" and "**compositions/router-query/SKILL.md** — for external
cache coordination with TanStack Query" with standard markdown links so the
references are navigable (e.g. use
[router-core/search-params/SKILL.md](router-core/search-params/SKILL.md) and
[compositions/router-query/SKILL.md](compositions/router-query/SKILL.md)),
keeping the trailing explanatory text and the code span `loaderDeps` intact.
packages/router-plugin/package.json (1)

103-103: Consider linting or syntax-checking the new bin.

These lines make bin/intent.js part of the shipped surface, but this package’s current CI only lint-checks ./src. A tiny node --check ./bin/intent.js or adding ./bin to the ESLint target would keep publish-time regressions from slipping through.

Also applies to: 154-155

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/router-plugin/package.json` at line 103, The package.json now
exposes "bin" (making bin/intent.js part of the shipped surface) but CI only
lints ./src, so add a publish-time syntax check for the new bin or include ./bin
in linting: update CI to run `node --check ./bin/intent.js` (or equivalent
syntax check) and/or add ./bin to the ESLint target so bin/intent.js (and the
other bin entry at lines 154-155) are checked before publishing.
packages/react-start/skills/_artifacts/skill_tree.yaml (1)

1-1: Header comment doesn't match actual file path.

The comment indicates skills/_artifacts/start_skill_tree.yaml but the file is located at packages/react-start/skills/_artifacts/skill_tree.yaml.

📝 Suggested fix
-# skills/_artifacts/start_skill_tree.yaml
+# packages/react-start/skills/_artifacts/skill_tree.yaml
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react-start/skills/_artifacts/skill_tree.yaml` at line 1, The header
comment at the top of the YAML incorrectly references "start_skill_tree.yaml";
update that comment to match the actual file name "skill_tree.yaml" by replacing
the text "skills/_artifacts/start_skill_tree.yaml" in the top-of-file comment
(the line that currently starts with "# ") with
"skills/_artifacts/skill_tree.yaml" so the header accurately reflects this
file's name and prevents confusion.
packages/start-server-core/skills/_artifacts/domain_map.yaml (1)

48-63: Keep the failure-mode records schema-consistent with the other artifacts.

These entries omit source, while the paired packages/start-server-core/skills/_artifacts/skill_spec.md already records one and the reviewed client-core domain map does the same in YAML. Adding it here would keep the machine-readable shape uniform.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/start-server-core/skills/_artifacts/domain_map.yaml` around lines 48
- 63, The two failure_mode entries under failure_modes (the ones with mistake
values "Missing AsyncLocalStorage setup" and "Incorrect handler export for
deployment target") are missing the required source field; update each entry to
include a source key with an appropriate identifier string (matching the schema
used in skill_spec.md and the client-core domain map) so the records are
schema-consistent while preserving existing keys mistake, mechanism, priority,
and status.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d232371a-f31e-496c-b398-32a3e2447e98

📥 Commits

Reviewing files that changed from the base of the PR and between 88fcbec and 142682c.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (83)
  • _artifacts/domain_map.yaml
  • _artifacts/skill_spec.md
  • _artifacts/skill_tree.yaml
  • _artifacts/start_domain_map.yaml
  • _artifacts/start_skill_tree.yaml
  • packages/react-router/bin/intent.js
  • packages/react-router/package.json
  • packages/react-router/skills/compositions/router-query/SKILL.md
  • packages/react-router/skills/lifecycle/migrate-from-react-router/SKILL.md
  • packages/react-router/skills/react-router/SKILL.md
  • packages/react-start/bin/intent.js
  • packages/react-start/package.json
  • packages/react-start/skills/_artifacts/domain_map.yaml
  • packages/react-start/skills/_artifacts/skill_spec.md
  • packages/react-start/skills/_artifacts/skill_tree.yaml
  • packages/react-start/skills/lifecycle/migrate-from-nextjs/SKILL.md
  • packages/react-start/skills/react-start/SKILL.md
  • packages/router-core/bin/intent.js
  • packages/router-core/package.json
  • packages/router-core/skills/router-core/SKILL.md
  • packages/router-core/skills/router-core/auth-and-guards/SKILL.md
  • packages/router-core/skills/router-core/code-splitting/SKILL.md
  • packages/router-core/skills/router-core/data-loading/SKILL.md
  • packages/router-core/skills/router-core/navigation/SKILL.md
  • packages/router-core/skills/router-core/not-found-and-errors/SKILL.md
  • packages/router-core/skills/router-core/path-params/SKILL.md
  • packages/router-core/skills/router-core/search-params/SKILL.md
  • packages/router-core/skills/router-core/search-params/references/validation-patterns.md
  • packages/router-core/skills/router-core/ssr/SKILL.md
  • packages/router-core/skills/router-core/type-safety/SKILL.md
  • packages/router-plugin/bin/intent.js
  • packages/router-plugin/package.json
  • packages/router-plugin/skills/_artifacts/domain_map.yaml
  • packages/router-plugin/skills/_artifacts/skill_spec.md
  • packages/router-plugin/skills/_artifacts/skill_tree.yaml
  • packages/router-plugin/skills/router-plugin/SKILL.md
  • packages/solid-router/bin/intent.js
  • packages/solid-router/package.json
  • packages/solid-router/skills/_artifacts/domain_map.yaml
  • packages/solid-router/skills/_artifacts/skill_spec.md
  • packages/solid-router/skills/_artifacts/skill_tree.yaml
  • packages/solid-router/skills/solid-router/SKILL.md
  • packages/solid-start/bin/intent.js
  • packages/solid-start/package.json
  • packages/solid-start/skills/_artifacts/domain_map.yaml
  • packages/solid-start/skills/_artifacts/skill_spec.md
  • packages/solid-start/skills/_artifacts/skill_tree.yaml
  • packages/solid-start/skills/solid-start/SKILL.md
  • packages/start-client-core/bin/intent.js
  • packages/start-client-core/package.json
  • packages/start-client-core/skills/_artifacts/domain_map.yaml
  • packages/start-client-core/skills/_artifacts/skill_spec.md
  • packages/start-client-core/skills/_artifacts/skill_tree.yaml
  • packages/start-client-core/skills/start-core/SKILL.md
  • packages/start-client-core/skills/start-core/deployment/SKILL.md
  • packages/start-client-core/skills/start-core/execution-model/SKILL.md
  • packages/start-client-core/skills/start-core/middleware/SKILL.md
  • packages/start-client-core/skills/start-core/server-functions/SKILL.md
  • packages/start-client-core/skills/start-core/server-routes/SKILL.md
  • packages/start-server-core/bin/intent.js
  • packages/start-server-core/package.json
  • packages/start-server-core/skills/_artifacts/domain_map.yaml
  • packages/start-server-core/skills/_artifacts/skill_spec.md
  • packages/start-server-core/skills/_artifacts/skill_tree.yaml
  • packages/start-server-core/skills/start-server-core/SKILL.md
  • packages/virtual-file-routes/bin/intent.js
  • packages/virtual-file-routes/package.json
  • packages/virtual-file-routes/skills/_artifacts/domain_map.yaml
  • packages/virtual-file-routes/skills/_artifacts/skill_spec.md
  • packages/virtual-file-routes/skills/_artifacts/skill_tree.yaml
  • packages/virtual-file-routes/skills/virtual-file-routes/SKILL.md
  • packages/vue-router/bin/intent.js
  • packages/vue-router/package.json
  • packages/vue-router/skills/_artifacts/domain_map.yaml
  • packages/vue-router/skills/_artifacts/skill_spec.md
  • packages/vue-router/skills/_artifacts/skill_tree.yaml
  • packages/vue-router/skills/vue-router/SKILL.md
  • packages/vue-start/bin/intent.js
  • packages/vue-start/package.json
  • packages/vue-start/skills/_artifacts/domain_map.yaml
  • packages/vue-start/skills/_artifacts/skill_spec.md
  • packages/vue-start/skills/_artifacts/skill_tree.yaml
  • packages/vue-start/skills/vue-start/SKILL.md

Comment on lines +178 to 180
"bin": {
"intent": "./bin/intent.js"
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

How do npm, pnpm, and Yarn handle package.json bin name collisions when multiple installed packages declare the same binary name?

💡 Result:

npm

  • Local installs (node_modules/.bin): bin name collisions are not treated as an error; the link/shim for a bin name can be replaced (effectively “last one linked wins”), because bin-links’ conflict check is skipped unless it’s a top-level global install (or --force is used). This is explicitly called out by binLinks.checkBins() “always returns successfully if global or top are false”. [1]
  • Global installs: modern npm refuses to overwrite an existing global bin unless the existing bin is already owned by the same package being installed (or you use --force). [2]

pnpm

  • pnpm links bins via @pnpm/link-bins, which deduplicates by bin name and resolves collisions deterministically before writing:
    1. If pnpm knows the project manifest, it prefers bins from direct dependencies over non-direct/hoisted ones (preferDirectCmds). [4]
    2. If there’s still a collision for the same bin name, it chooses based on:
      • whether the bin name matches the package’s own name (ownName wins),
      • otherwise by package name (lexicographic),
      • and if it’s the same package, by version (higher wins). [4]
    • The skipped option is logged (debug) via a “bins-conflict” logger. [4]

Yarn

  • Yarn Classic (v1) (and Yarn’s node-modules linker behavior) relies on the same underlying bin-links behavior: it can check for conflicting bins that would prevent linking, but that check is primarily relevant to top-level global installs; for local installs, the conflict check is effectively bypassed (same rule: global/top must be true to enforce). [1], [5]
  • Additionally, the bin-links advisory history notes that (historically) global bin overwrites were possible, while this behavior was “still allowed in local installations”. [3]

Avoid publishing the same intent bin from every package.

Line 178 adds a public intent binary here, but the PR does the same in multiple TanStack packages. When a consumer installs @tanstack/react-router, they will also have @tanstack/router-core in node_modules, and only one node_modules/.bin/intent shim can be active. In npm and Yarn, the last package linked wins (order-dependent); in pnpm, the binary is resolved based on dependency precedence rules. In all cases, which intent implementation gets invoked is outside your control and may not be the one consumers expect. Consider publishing intent from a single package or namespacing these binaries instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/router-core/package.json` around lines 178 - 180, This package
currently exposes a top-level CLI via the "bin" entry ("intent":
"./bin/intent.js"), which conflicts with identical bins published from other
TanStack packages; remove or change this export so consumers don't get an
ambiguous / conflicting node_modules/.bin/intent. Either remove the "bin" entry
from this package.json so only a single chosen package publishes "intent", or
rename/namespace the binary here (e.g., "intent-router-core") and update the
corresponding ./bin/intent.js filename and any references; update whichever
package will remain the authoritative publisher to keep the original "intent"
bin.

Comment on lines +126 to +140
```ts
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { tanstackRouter } from '@tanstack/router-plugin/vite'
import { routes } from './routes'

export default defineConfig({
plugins: [
tanstackRouter({
target: 'react',
virtualRouteConfig: routes,
}),
react(),
],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

fd -t f "SKILL.md" packages/virtual-file-routes 2>/dev/null | head -5

Repository: TanStack/router

Length of output: 123


🏁 Script executed:

cat -n packages/virtual-file-routes/skills/virtual-file-routes/SKILL.md | head -150

Repository: TanStack/router

Length of output: 4823


🏁 Script executed:

cat -n packages/virtual-file-routes/skills/virtual-file-routes/SKILL.md | sed -n '120,220p'

Repository: TanStack/router

Length of output: 3131


🏁 Script executed:

rg "target:" packages/virtual-file-routes -A 2 -B 2

Repository: TanStack/router

Length of output: 894


🏁 Script executed:

rg "solid\|vue\|angular" packages/virtual-file-routes/skills -i

Repository: TanStack/router

Length of output: 41


🏁 Script executed:

fd -t f "\.md$" packages/router-plugin | head -10

Repository: TanStack/router

Length of output: 253


🏁 Script executed:

rg "target.*solid\|target.*vue" packages --max-count 5

Repository: TanStack/router

Length of output: 41


🏁 Script executed:

cat -n packages/router-plugin/skills/router-plugin/SKILL.md | head -200

Repository: TanStack/router

Length of output: 8268


🏁 Script executed:

rg "target.*['\"]" packages/router-plugin -A 1 -B 1 | head -50

Repository: TanStack/router

Length of output: 3500


Show framework-agnostic integration example for virtual-file-routes.

The virtual-file-routes library is framework-agnostic, but the integration example (lines 126–141) hardcodes React setup with @vitejs/plugin-react, react(), and target: 'react'. This will mislead users building with Solid or Vue into copying React-specific configuration. Show only the router plugin setup with a placeholder for the target framework.

✏️ Suggested adjustment
 // vite.config.ts
 import { defineConfig } from 'vite'
-import react from '@vitejs/plugin-react'
 import { tanstackRouter } from '@tanstack/router-plugin/vite'
 import { routes } from './routes'

 export default defineConfig({
   plugins: [
     tanstackRouter({
-      target: 'react',
+      target: 'react', // or 'solid', 'vue'
       virtualRouteConfig: routes,
     }),
-    react(),
+    // Add your framework's Vite plugin here
   ],
 })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/virtual-file-routes/skills/virtual-file-routes/SKILL.md` around
lines 126 - 140, The example in SKILL.md hardcodes React-specific setup; instead
update the vite.config.ts snippet to show only the tanstackRouter plugin
configuration with virtualRouteConfig: routes and a placeholder for the target
(e.g., target: '<framework>') so users know to substitute 'react'/'solid'/'vue';
reference the tanstackRouter call, the virtualRouteConfig option, and the routes
identifier when making this change.

- Fix incorrect createTanstackRouter → createRouter in router-query examples
- Fix missing React type imports (ComponentPropsWithoutRef, FormEvent)
- Fix hardcoded localhost:3000 in SSR example, use req headers instead
- Fix session.update/clear to use await with data payload
- Fix start-setup → start-core slug mismatch in domain_map + skill_spec
- Make start-client-core skill_tree self-contained (remove react-start refs)
- Add framework-agnostic comments to execution-model and middleware skills
- Make virtual-file-routes vite example framework-agnostic
- Fix solid-router domain_map: Link is primary, createLink for wrappers
- Fix vue-router domain_map: scope Ref unwrapping to script, not templates
- Fix vue-router SKILL.md: tsx → vue fence language for template snippets
- Fix virtual-file-routes domain_map failure mode wording
- Fix MD028 blockquote blank lines across 11 files
- Fix MD040 missing fence languages across 4 files
- Update pnpm-lock.yaml
@github-actions
Copy link
Contributor

github-actions bot commented Mar 9, 2026

Bundle Size Benchmarks

  • Commit: 6438c03b2f29
  • Measured at: 2026-03-09T21:25:12.114Z
  • Baseline source: history:31ed0a96489f
  • Dashboard: bundle-size history
Scenario Current (gzip) Delta vs baseline Raw Brotli Trend
react-router.minimal 87.01 KiB 0 B (0.00%) 273.70 KiB 75.55 KiB ▁▁▁▁▁▁▁▁▁▁█
react-router.full 90.00 KiB 0 B (0.00%) 283.96 KiB 78.37 KiB ▁▁▁▁▁▁▁▁▁▁█
solid-router.minimal 36.32 KiB 0 B (0.00%) 108.81 KiB 32.63 KiB ▁▁▁▁▁▁▁▁▁▁█
solid-router.full 40.61 KiB 0 B (0.00%) 121.79 KiB 36.46 KiB ▁▁▁▁▁▁▁▁▁▁█
vue-router.minimal 52.17 KiB 0 B (0.00%) 148.83 KiB 46.92 KiB ▁▁▁▁▁▁▁▁▁▁█
vue-router.full 56.96 KiB 0 B (0.00%) 164.34 KiB 51.11 KiB ▁▁▁▁▁▁▁▁▁▁█
react-start.minimal 99.54 KiB 0 B (0.00%) 312.85 KiB 86.11 KiB ▁▁▁▁▁▁▁▁▁▁█
react-start.full 102.90 KiB 0 B (0.00%) 322.58 KiB 88.98 KiB ▁▁▁▁▁▁▁▁▁▁█
solid-start.minimal 48.63 KiB 0 B (0.00%) 146.40 KiB 43.07 KiB ▁▁▁▁▁▁▁▁▁▁█
solid-start.full 54.09 KiB 0 B (0.00%) 162.27 KiB 47.67 KiB ▁▁▁▁▁▁▁▁▁▁█

Trend sparkline is historical gzip bytes ending with this PR measurement; lower is better.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 9, 2026

More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/@tanstack/arktype-adapter@6866

@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/@tanstack/eslint-plugin-router@6866

@tanstack/history

npm i https://pkg.pr.new/@tanstack/history@6866

@tanstack/nitro-v2-vite-plugin

npm i https://pkg.pr.new/@tanstack/nitro-v2-vite-plugin@6866

@tanstack/react-router

npm i https://pkg.pr.new/@tanstack/react-router@6866

@tanstack/react-router-devtools

npm i https://pkg.pr.new/@tanstack/react-router-devtools@6866

@tanstack/react-router-ssr-query

npm i https://pkg.pr.new/@tanstack/react-router-ssr-query@6866

@tanstack/react-start

npm i https://pkg.pr.new/@tanstack/react-start@6866

@tanstack/react-start-client

npm i https://pkg.pr.new/@tanstack/react-start-client@6866

@tanstack/react-start-server

npm i https://pkg.pr.new/@tanstack/react-start-server@6866

@tanstack/router-cli

npm i https://pkg.pr.new/@tanstack/router-cli@6866

@tanstack/router-core

npm i https://pkg.pr.new/@tanstack/router-core@6866

@tanstack/router-devtools

npm i https://pkg.pr.new/@tanstack/router-devtools@6866

@tanstack/router-devtools-core

npm i https://pkg.pr.new/@tanstack/router-devtools-core@6866

@tanstack/router-generator

npm i https://pkg.pr.new/@tanstack/router-generator@6866

@tanstack/router-plugin

npm i https://pkg.pr.new/@tanstack/router-plugin@6866

@tanstack/router-ssr-query-core

npm i https://pkg.pr.new/@tanstack/router-ssr-query-core@6866

@tanstack/router-utils

npm i https://pkg.pr.new/@tanstack/router-utils@6866

@tanstack/router-vite-plugin

npm i https://pkg.pr.new/@tanstack/router-vite-plugin@6866

@tanstack/solid-router

npm i https://pkg.pr.new/@tanstack/solid-router@6866

@tanstack/solid-router-devtools

npm i https://pkg.pr.new/@tanstack/solid-router-devtools@6866

@tanstack/solid-router-ssr-query

npm i https://pkg.pr.new/@tanstack/solid-router-ssr-query@6866

@tanstack/solid-start

npm i https://pkg.pr.new/@tanstack/solid-start@6866

@tanstack/solid-start-client

npm i https://pkg.pr.new/@tanstack/solid-start-client@6866

@tanstack/solid-start-server

npm i https://pkg.pr.new/@tanstack/solid-start-server@6866

@tanstack/start-client-core

npm i https://pkg.pr.new/@tanstack/start-client-core@6866

@tanstack/start-fn-stubs

npm i https://pkg.pr.new/@tanstack/start-fn-stubs@6866

@tanstack/start-plugin-core

npm i https://pkg.pr.new/@tanstack/start-plugin-core@6866

@tanstack/start-server-core

npm i https://pkg.pr.new/@tanstack/start-server-core@6866

@tanstack/start-static-server-functions

npm i https://pkg.pr.new/@tanstack/start-static-server-functions@6866

@tanstack/start-storage-context

npm i https://pkg.pr.new/@tanstack/start-storage-context@6866

@tanstack/valibot-adapter

npm i https://pkg.pr.new/@tanstack/valibot-adapter@6866

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/@tanstack/virtual-file-routes@6866

@tanstack/vue-router

npm i https://pkg.pr.new/@tanstack/vue-router@6866

@tanstack/vue-router-devtools

npm i https://pkg.pr.new/@tanstack/vue-router-devtools@6866

@tanstack/vue-router-ssr-query

npm i https://pkg.pr.new/@tanstack/vue-router-ssr-query@6866

@tanstack/vue-start

npm i https://pkg.pr.new/@tanstack/vue-start@6866

@tanstack/vue-start-client

npm i https://pkg.pr.new/@tanstack/vue-start-client@6866

@tanstack/vue-start-server

npm i https://pkg.pr.new/@tanstack/vue-start-server@6866

@tanstack/zod-adapter

npm i https://pkg.pr.new/@tanstack/zod-adapter@6866

commit: 2be0c14

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

♻️ Duplicate comments (4)
packages/start-client-core/skills/_artifacts/domain_map.yaml (1)

8-17: ⚠️ Potential issue | 🟠 Major

Make the package-local domain map describe the package it ships with.

This file lives under packages/start-client-core, but Lines 9-17 still identify it as @tanstack/react-start with primary_framework: 'React'. That conflicts with the sibling package-local skill_tree.yaml, and it makes the published metadata look React-specific even though this package is the framework-agnostic core. Either align the library block with @tanstack/start-client-core, or move this consolidated React Start descriptor to the repo-level artifact instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/start-client-core/skills/_artifacts/domain_map.yaml` around lines 8
- 17, The library metadata in the domain_map.yaml is incorrect for this package:
update the library block that currently sets name: '@tanstack/react-start' and
primary_framework: 'React' so it accurately describes this package (e.g., name
'@tanstack/start-client-core' and a framework-agnostic primary_framework) or
remove/move this consolidated React-specific descriptor to the repo-level
artifact; edit the library block in domain_map.yaml (the fields name, version if
needed, description, and primary_framework) to align with the package-local
skill_tree.yaml and the actual package purpose.
packages/start-client-core/skills/start-core/server-routes/SKILL.md (1)

24-77: ⚠️ Potential issue | 🟠 Major

Keep this core skill framework-agnostic.

Lines 26-27, 45-46, 112-113, and 129-130 hard-code @tanstack/react-router, and Lines 46-77 add a React-only useState UI example. Because this file ships from packages/start-client-core, agents following it for Solid/Vue Start will learn the wrong bindings. Please rewrite these snippets with framework-neutral placeholders or move the binding-specific examples into the framework package skills.

Also applies to: 110-154, 198-249

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/start-client-core/skills/start-core/server-routes/SKILL.md` around
lines 24 - 77, The file hard-codes React and `@tanstack/react-router` usage
(imports of "@tanstack/react-router", createFileRoute usage tied to React, and
the HelloComponent using useState) which makes the core skill
framework-specific; replace those snippets with framework-neutral placeholders
or abstract examples: remove the direct import of "@tanstack/react-router" and
instead reference a generic "createFileRoute" or "router-lib" placeholder,
replace the React-only HelloComponent and useState example with a neutral
client-side example (e.g., describe a fetch POST workflow or show pseudocode for
a UI handler) or move the React-specific example into the React framework skill
package, and update all occurrences of Route, createFileRoute, HelloComponent,
and any React hooks so the core package remains framework-agnostic.
packages/start-client-core/skills/start-core/execution-model/SKILL.md (1)

44-154: ⚠️ Potential issue | 🟠 Major

This still teaches React bindings in a framework-neutral skill.

Lines 46, 63, 77, 88, 103, 121, and 147 still hard-code @tanstack/react-start, @tanstack/react-router, and React.ReactNode. Agents using the core skill from Solid/Vue Start will copy the React packages/types from here. Keep this skill binding-agnostic and move concrete React snippets into react-start.

Based on learnings, Separate framework-agnostic core logic from React/Solid bindings.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/start-client-core/skills/start-core/execution-model/SKILL.md` around
lines 44 - 154, The SKILL.md contains framework-specific React bindings (imports
and types) that make the core skill non-agnostic; replace hard-coded usages of
`@tanstack/react-start`, `@tanstack/react-router`, and React.ReactNode in the
examples and prose with framework-neutral placeholders (e.g.,
`@tanstack/`<framework>-start or “your framework’s start package”) and generic
types (e.g., “Component children” or “framework-specific node”), and relocate
the concrete React examples for createServerFn, createServerOnlyFn,
createClientOnlyFn, ClientOnly, useHydrated, and createIsomorphicFn into the
react-start/react-router package docs so the core SKILL.md only shows
framework-agnostic snippets and references where framework-specific
implementations live.
packages/virtual-file-routes/skills/virtual-file-routes/SKILL.md (1)

143-149: ⚠️ Potential issue | 🟡 Minor

Keep the file-path example framework-agnostic too.

Line 147 still hardcodes target: 'react'. Since this skill is framework-agnostic, that alternate snippet can still steer Solid/Vue agents toward an invalid plugin target.

✏️ Suggested adjustment
 tanstackRouter({
-  target: 'react',
+  target: '<framework>', // 'react' | 'solid' | 'vue'
   virtualRouteConfig: './routes.ts',
 })

Verify by comparing the two snippets in this file and scanning other virtualRouteConfig examples:

#!/bin/bash
set -euo pipefail

echo "Generic integration example in this skill:"
sed -n '126,140p' packages/virtual-file-routes/skills/virtual-file-routes/SKILL.md

echo
echo "File-path variant under review:"
sed -n '143,149p' packages/virtual-file-routes/skills/virtual-file-routes/SKILL.md

echo
echo "Other tanstackRouter + virtualRouteConfig examples in docs/skills:"
rg -n -C2 "virtualRouteConfig|target:\s*'(react|solid|vue)'|target:\s*'<framework>'" \
  packages/virtual-file-routes \
  packages/router-plugin \
  docs/router \
  -g '*.md'

Expected result: the file-path variant should follow the same framework-agnostic pattern as the main example instead of leaving a React-only default.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/virtual-file-routes/skills/virtual-file-routes/SKILL.md` around
lines 143 - 149, The example snippet hardcodes target: 'react' which breaks the
skill's framework-agnostic intent; update the file-path variant that uses
tanstackRouter and virtualRouteConfig ('./routes.ts') to either remove the
hardcoded target or replace it with a neutral placeholder like target:
'<framework>' so it matches the generic example elsewhere in SKILL.md and avoids
steering Solid/Vue users to an invalid plugin target.
🧹 Nitpick comments (1)
packages/vue-router/skills/vue-router/SKILL.md (1)

66-90: Consider clarifying JSX setup or using SFC examples.

The route component examples use JSX syntax (fragments <>, function components returning JSX), but the Vite config only shows @vitejs/plugin-vue. Vue JSX requires @vitejs/plugin-vue-jsx. Most Vue developers use SFC templates, so this could cause confusion.

Consider either:

  1. Adding a note that JSX requires @vitejs/plugin-vue-jsx
  2. Using Vue SFC (.vue files) for these examples to match typical Vue patterns
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/vue-router/skills/vue-router/SKILL.md` around lines 66 - 90, The
example uses JSX (RootLayout with fragments and Link/Outlet JSX) but the
docs/config only mention `@vitejs/plugin-vue`; update the example or note: either
add a clarifying comment that using JSX/TSX requires installing and enabling
`@vitejs/plugin-vue-jsx` in Vite, or replace the snippet with an equivalent Single
File Component (.vue) example (e.g., export default component using <template>
with <router-link> and <router-view>), and reference the createRootRoute, Route,
and RootLayout symbols so readers can find and update the code consistently.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/react-router/skills/compositions/router-query/SKILL.md`:
- Around line 340-358: Rename the example functions to avoid shadowing the
imported createRouter: change both example function declarations from
createRouter() to createAppRouter() (and update any internal references) so they
call the imported createRouter from `@tanstack/react-router` instead of recursing;
ensure both the "WRONG" and "CORRECT" snippets use createAppRouter and keep the
context/queryClient logic identical to the shown examples.

In `@packages/react-router/skills/lifecycle/migrate-from-react-router/SKILL.md`:
- Around line 34-39: The installation instructions wrongly mark
`@tanstack/react-router-devtools` as a devDependency even though the guide
imports/uses TanStackRouterDevtools at runtime; update the commands so
`@tanstack/react-router-devtools` is installed as a regular dependency (move it
from the -D line into the main npm install command) and keep only
`@tanstack/router-plugin` as a devDependency, ensuring the runtime import
(TanStackRouterDevtools) is available in production builds.
- Around line 23-24: Update the CRITICAL migration note and the cleanup/search
instructions to include react-router-dom alongside react-router: modify the
warning sentence that currently references only `react-router` (the CRITICAL
note) to mention both `react-router` and `react-router-dom`, and add
corresponding grep/search commands for `react-router-dom` where the current grep
commands for `react-router` appear (the grep lines referenced near the end of
the document) so stale `react-router-dom` imports are detected and removed
during the uninstall/cleanup step.

In `@packages/react-router/skills/react-router/SKILL.md`:
- Around line 451-472: The example incorrectly recreates the router with
changing auth (useMemo) instead of creating the router once with a placeholder
context and injecting the live auth via RouterProvider; update the code so
createRouter({ routeTree, context: { auth: undefined! } }) is called once (e.g.,
at module scope or top-level of App), remove the useMemo recreation in App,
create an InnerApp that calls useAuth(), and render <RouterProvider
router={router} context={{ auth }} /> inside that InnerApp, wrapping InnerApp
with your AuthProvider in App.

In `@packages/router-core/skills/router-core/type-safety/SKILL.md`:
- Around line 252-266: The code fence redeclares `const props` and places an
`import` after statements, producing invalid TypeScript; split into separate,
self-contained snippets so each example compiles independently: (1) show the
wrong example with `import type { LinkProps }` at the top and `const props:
LinkProps = { to: '/posts' }`, (2) show the correct `as const satisfies
LinkProps` variant with its own import if needed, and (3) show the narrowed
generic example with `import type { RegisteredRouter }` (and `LinkProps`) at the
top and `const props = { to: '/posts' } as const satisfies
LinkProps<RegisteredRouter, string, '/posts'>`; ensure no duplicate `const
props` in the same snippet and place imports before usage so each snippet is
independently valid.
- Around line 107-115: The route example throws redirect(...) in beforeLoad but
never imports redirect, making the snippet invalid; update the top import to
include redirect alongside createFileRoute (e.g., import { createFileRoute,
redirect } from '@tanstack/react-router') so Route's beforeLoad can call
redirect; ensure the symbol names referenced are createFileRoute, redirect, and
beforeLoad in the Route definition.

In `@packages/start-server-core/bin/intent.js`:
- Around line 8-18: The catch block that currently treats any
ERR_MODULE_NOT_FOUND / MODULE_NOT_FOUND as "@tanstack/intent is not installed"
is too broad; update the handler to verify the missing-module message actually
references "@tanstack/intent" (e.g., inspect e.message or e.requireStack for
"Cannot find module '@tanstack/intent'" or the module name string) before
printing the install prompt, otherwise rethrow or print the original error and
exit; modify the catch around the dynamic import (the try/catch handling e) to
check e?.code and e?.message.includes('@tanstack/intent') (or similar) and only
show the installation/helpful console.error lines and process.exit(1) when the
missing module is indeed `@tanstack/intent`, otherwise surface the real error.

In `@packages/start-server-core/skills/start-server-core/SKILL.md`:
- Around line 20-22: The two consecutive blockquote paragraphs in SKILL.md (the
lines starting with "**CRITICAL**: These utilities are SERVER-ONLY..." and
"**CRITICAL**: Types are FULLY INFERRED...") currently have an extra blank line
that trips markdownlint MD028; remove the empty line between those blockquote
lines (or merge them into a single contiguous blockquote) so there is no blank
line inside the blockquote, preserving the existing wording and punctuation.
- Around line 53-64: Several markdown code blocks in SKILL.md call
createServerFn but omit its import; update every snippet that invokes
createServerFn (the blocks showing serverFn =
createServerFn({...}).handler(...)) to include the missing import statement: add
import { createServerFn } from '@tanstack/react-start' at the top of each of
those code fences so each example is self-contained and copy-pasteable.

In `@packages/vue-router/skills/vue-router/SKILL.md`:
- Around line 304-315: The Vue SFC example includes JavaScript-style comments
outside a <script> block (the "// SFC template... MyRoute.component.vue" line)
which will break if copied into an .vue file; replace that leading // comment
with an HTML comment (e.g., <!-- MyRoute.component.vue - SFC template -->) or
move the explanatory text above the code block in markdown, leaving the
<template> and <script setup> (and the useLoaderData/data usage) intact.

---

Duplicate comments:
In `@packages/start-client-core/skills/_artifacts/domain_map.yaml`:
- Around line 8-17: The library metadata in the domain_map.yaml is incorrect for
this package: update the library block that currently sets name:
'@tanstack/react-start' and primary_framework: 'React' so it accurately
describes this package (e.g., name '@tanstack/start-client-core' and a
framework-agnostic primary_framework) or remove/move this consolidated
React-specific descriptor to the repo-level artifact; edit the library block in
domain_map.yaml (the fields name, version if needed, description, and
primary_framework) to align with the package-local skill_tree.yaml and the
actual package purpose.

In `@packages/start-client-core/skills/start-core/execution-model/SKILL.md`:
- Around line 44-154: The SKILL.md contains framework-specific React bindings
(imports and types) that make the core skill non-agnostic; replace hard-coded
usages of `@tanstack/react-start`, `@tanstack/react-router`, and React.ReactNode in
the examples and prose with framework-neutral placeholders (e.g.,
`@tanstack/`<framework>-start or “your framework’s start package”) and generic
types (e.g., “Component children” or “framework-specific node”), and relocate
the concrete React examples for createServerFn, createServerOnlyFn,
createClientOnlyFn, ClientOnly, useHydrated, and createIsomorphicFn into the
react-start/react-router package docs so the core SKILL.md only shows
framework-agnostic snippets and references where framework-specific
implementations live.

In `@packages/start-client-core/skills/start-core/server-routes/SKILL.md`:
- Around line 24-77: The file hard-codes React and `@tanstack/react-router` usage
(imports of "@tanstack/react-router", createFileRoute usage tied to React, and
the HelloComponent using useState) which makes the core skill
framework-specific; replace those snippets with framework-neutral placeholders
or abstract examples: remove the direct import of "@tanstack/react-router" and
instead reference a generic "createFileRoute" or "router-lib" placeholder,
replace the React-only HelloComponent and useState example with a neutral
client-side example (e.g., describe a fetch POST workflow or show pseudocode for
a UI handler) or move the React-specific example into the React framework skill
package, and update all occurrences of Route, createFileRoute, HelloComponent,
and any React hooks so the core package remains framework-agnostic.

In `@packages/virtual-file-routes/skills/virtual-file-routes/SKILL.md`:
- Around line 143-149: The example snippet hardcodes target: 'react' which
breaks the skill's framework-agnostic intent; update the file-path variant that
uses tanstackRouter and virtualRouteConfig ('./routes.ts') to either remove the
hardcoded target or replace it with a neutral placeholder like target:
'<framework>' so it matches the generic example elsewhere in SKILL.md and avoids
steering Solid/Vue users to an invalid plugin target.

---

Nitpick comments:
In `@packages/vue-router/skills/vue-router/SKILL.md`:
- Around line 66-90: The example uses JSX (RootLayout with fragments and
Link/Outlet JSX) but the docs/config only mention `@vitejs/plugin-vue`; update the
example or note: either add a clarifying comment that using JSX/TSX requires
installing and enabling `@vitejs/plugin-vue-jsx` in Vite, or replace the snippet
with an equivalent Single File Component (.vue) example (e.g., export default
component using <template> with <router-link> and <router-view>), and reference
the createRootRoute, Route, and RootLayout symbols so readers can find and
update the code consistently.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4b8d9909-3c64-4d2e-86ed-62f9fe37b901

📥 Commits

Reviewing files that changed from the base of the PR and between 142682c and ec661f4.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (33)
  • packages/react-router/bin/intent.js
  • packages/react-router/skills/compositions/router-query/SKILL.md
  • packages/react-router/skills/lifecycle/migrate-from-react-router/SKILL.md
  • packages/react-router/skills/react-router/SKILL.md
  • packages/react-start/bin/intent.js
  • packages/router-core/skills/router-core/auth-and-guards/SKILL.md
  • packages/router-core/skills/router-core/not-found-and-errors/SKILL.md
  • packages/router-core/skills/router-core/search-params/SKILL.md
  • packages/router-core/skills/router-core/ssr/SKILL.md
  • packages/router-core/skills/router-core/type-safety/SKILL.md
  • packages/router-plugin/bin/intent.js
  • packages/solid-router/bin/intent.js
  • packages/solid-router/skills/_artifacts/domain_map.yaml
  • packages/solid-router/skills/solid-router/SKILL.md
  • packages/solid-start/bin/intent.js
  • packages/start-client-core/bin/intent.js
  • packages/start-client-core/skills/_artifacts/domain_map.yaml
  • packages/start-client-core/skills/_artifacts/skill_spec.md
  • packages/start-client-core/skills/_artifacts/skill_tree.yaml
  • packages/start-client-core/skills/start-core/SKILL.md
  • packages/start-client-core/skills/start-core/execution-model/SKILL.md
  • packages/start-client-core/skills/start-core/middleware/SKILL.md
  • packages/start-client-core/skills/start-core/server-functions/SKILL.md
  • packages/start-client-core/skills/start-core/server-routes/SKILL.md
  • packages/start-server-core/bin/intent.js
  • packages/start-server-core/skills/start-server-core/SKILL.md
  • packages/virtual-file-routes/bin/intent.js
  • packages/virtual-file-routes/skills/_artifacts/domain_map.yaml
  • packages/virtual-file-routes/skills/virtual-file-routes/SKILL.md
  • packages/vue-router/bin/intent.js
  • packages/vue-router/skills/_artifacts/domain_map.yaml
  • packages/vue-router/skills/vue-router/SKILL.md
  • packages/vue-start/bin/intent.js
✅ Files skipped from review due to trivial changes (2)
  • packages/router-core/skills/router-core/not-found-and-errors/SKILL.md
  • packages/router-core/skills/router-core/search-params/SKILL.md
🚧 Files skipped from review as they are similar to previous changes (13)
  • packages/start-client-core/skills/_artifacts/skill_spec.md
  • packages/react-router/bin/intent.js
  • packages/start-client-core/bin/intent.js
  • packages/vue-start/bin/intent.js
  • packages/start-client-core/skills/start-core/SKILL.md
  • packages/router-core/skills/router-core/ssr/SKILL.md
  • packages/vue-router/skills/_artifacts/domain_map.yaml
  • packages/start-client-core/skills/start-core/server-functions/SKILL.md
  • packages/react-start/bin/intent.js
  • packages/start-client-core/skills/start-core/middleware/SKILL.md
  • packages/virtual-file-routes/bin/intent.js
  • packages/solid-start/bin/intent.js
  • packages/solid-router/bin/intent.js

Comment on lines +340 to +358
```tsx
// WRONG — shared across SSR requests
const queryClient = new QueryClient()
export function createRouter() {
return createRouter({
routeTree,
context: { queryClient },
})
}

// CORRECT — new QueryClient per createRouter call
export function createRouter() {
const queryClient = new QueryClient()
return createRouter({
routeTree,
context: { queryClient },
})
}
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix function naming collision in common mistake example.

Both the "WRONG" and "CORRECT" examples define a function named createRouter that calls createRouter internally. This creates a naming collision where the function name shadows the imported createRouter from @tanstack/react-router, leading to potential infinite recursion and confusion.

The function should be named createAppRouter to match the naming convention used consistently in earlier SSR examples (lines 93, 129, 164).

🐛 Proposed fix
 // WRONG — shared across SSR requests
 const queryClient = new QueryClient()
-export function createRouter() {
+export function createAppRouter() {
   return createRouter({
     routeTree,
     context: { queryClient },
   })
 }

 // CORRECT — new QueryClient per createRouter call
-export function createRouter() {
+export function createAppRouter() {
   const queryClient = new QueryClient()
   return createRouter({
     routeTree,
     context: { queryClient },
   })
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react-router/skills/compositions/router-query/SKILL.md` around lines
340 - 358, Rename the example functions to avoid shadowing the imported
createRouter: change both example function declarations from createRouter() to
createAppRouter() (and update any internal references) so they call the imported
createRouter from `@tanstack/react-router` instead of recursing; ensure both the
"WRONG" and "CORRECT" snippets use createAppRouter and keep the
context/queryClient logic identical to the shown examples.

Comment on lines +23 to +24
> **CRITICAL**: If your UI is blank after migration, open the console. Errors like "cannot use useNavigate outside of context" mean React Router imports remain alongside TanStack Router imports. Uninstall `react-router` to surface them as TypeScript errors.
> **CRITICAL**: TanStack Router uses `to` + `params` for navigation, NOT template literal paths. Never interpolate params into the `to` string.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "SKILL.md" | grep -i "migrate-from-react-router"

Repository: TanStack/router

Length of output: 134


🏁 Script executed:

# Get the file size first to determine how to read it
wc -l packages/react-router/skills/lifecycle/migrate-from-react-router/SKILL.md

Repository: TanStack/router

Length of output: 136


🏁 Script executed:

# Read the specific lines mentioned in the review
sed -n '20,30p' packages/react-router/skills/lifecycle/migrate-from-react-router/SKILL.md

Repository: TanStack/router

Length of output: 635


🏁 Script executed:

# Also check lines 381-392
sed -n '375,395p' packages/react-router/skills/lifecycle/migrate-from-react-router/SKILL.md

Repository: TanStack/router

Length of output: 411


🌐 Web query:

React Router v7 react-router-dom compatibility re-export

💡 Result:

In React Router v7, react-router-dom is kept only as a compatibility/migration package: it is still published and re-exports everything from react-router to ease upgrades from v6, but the recommended direction is to import from react-router going forward. [1]

If you’re coming from Remix: Remix notes that React Router v7 is released, and Remix itself re-exports the React Router DOM APIs, so you typically don’t need to install React Router separately in a Remix app. [2]

Implication: for v7 apps, prefer import { ... } from "react-router"; keep react-router-dom only to avoid churn while migrating older code that imports from "react-router-dom". [1]

Sources:
[1] React Router changelog (migration note about react-router-dom re-exporting react-router) (reactrouter.com)
[2] Remix docs discussion of React Router v7 / re-exports (v2.remix.run)

Citations:


Add react-router-dom to cleanup instructions and grep searches.

React Router v7 re-exports react-router-dom from react-router for migration compatibility. The CRITICAL message at line 23 and the grep commands at lines 389–390 should include react-router-dom alongside react-router. The npm uninstall command already covers both, but the search steps miss react-router-dom imports, leaving stale ones undetected.

Update line 23 to mention both packages, and add grep commands for react-router-dom:

Suggested fix
-> **CRITICAL**: If your UI is blank after migration, open the console. Errors like "cannot use useNavigate outside of context" mean React Router imports remain alongside TanStack Router imports. Uninstall `react-router` to surface them as TypeScript errors.
+> **CRITICAL**: If your UI is blank after migration, open the console. Errors like "cannot use useNavigate outside of context" mean React Router imports remain alongside TanStack Router imports. Uninstall `react-router` and `react-router-dom` to surface them as TypeScript errors.
 
 grep -r "from 'react-router" src/
 grep -r 'from "react-router' src/
+grep -r "from 'react-router-dom" src/
+grep -r 'from "react-router-dom' src/
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react-router/skills/lifecycle/migrate-from-react-router/SKILL.md`
around lines 23 - 24, Update the CRITICAL migration note and the cleanup/search
instructions to include react-router-dom alongside react-router: modify the
warning sentence that currently references only `react-router` (the CRITICAL
note) to mention both `react-router` and `react-router-dom`, and add
corresponding grep/search commands for `react-router-dom` where the current grep
commands for `react-router` appear (the grep lines referenced near the end of
the document) so stale `react-router-dom` imports are detected and removed
during the uninstall/cleanup step.

Comment on lines +34 to +39
- [ ] **Install TanStack Router alongside React Router temporarily**

```bash
npm install @tanstack/react-router
npm install -D @tanstack/router-plugin @tanstack/react-router-devtools
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Check if the file exists and read the relevant sections
fd "SKILL.md" packages/react-router/skills/lifecycle/migrate-from-react-router/

Repository: TanStack/router

Length of output: 132


🏁 Script executed:

# Read the file to see the context around the installation command and devtools usage
cat -n packages/react-router/skills/lifecycle/migrate-from-react-router/SKILL.md | head -100

Repository: TanStack/router

Length of output: 3557


🏁 Script executed:

# Check if there are any other installation examples in the codebase
rg "@tanstack/react-router-devtools" -A 3 -B 3 -i

Repository: TanStack/router

Length of output: 50374


🏁 Script executed:

# Look for package.json files in the repo to see how devtools is installed elsewhere
fd "package.json" -x grep -l "@tanstack/react-router-devtools" {} \;

Repository: TanStack/router

Length of output: 4855


🏁 Script executed:

# Check the other SKILL.md file for the same pattern
grep -n "@tanstack/react-router-devtools" packages/react-router/skills/react-router/SKILL.md

Repository: TanStack/router

Length of output: 208


🏁 Script executed:

# Verify the package structure - check if devtools is truly a runtime dependency
cat packages/react-router-devtools/package.json | head -20

Repository: TanStack/router

Length of output: 600


Install @tanstack/react-router-devtools as a runtime dependency, not -D.

The guide imports and renders TanStackRouterDevtools in application code, but documents it as a devDependency. Teams running npm install --production in CI will have production builds fail with missing imports. Move @tanstack/react-router-devtools to the main install command and keep only @tanstack/router-plugin as -D.

Suggested fix
 npm install `@tanstack/react-router`
-npm install -D `@tanstack/router-plugin` `@tanstack/react-router-devtools`
+npm install `@tanstack/react-router-devtools`
+npm install -D `@tanstack/router-plugin`
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- [ ] **Install TanStack Router alongside React Router temporarily**
```bash
npm install @tanstack/react-router
npm install -D @tanstack/router-plugin @tanstack/react-router-devtools
```
- [ ] **Install TanStack Router alongside React Router temporarily**
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react-router/skills/lifecycle/migrate-from-react-router/SKILL.md`
around lines 34 - 39, The installation instructions wrongly mark
`@tanstack/react-router-devtools` as a devDependency even though the guide
imports/uses TanStackRouterDevtools at runtime; update the commands so
`@tanstack/react-router-devtools` is installed as a regular dependency (move it
from the -D line into the main npm install command) and keep only
`@tanstack/router-plugin` as a devDependency, ensuring the runtime import
(TanStackRouterDevtools) is available in production builds.

Comment on lines +451 to +472
### 2. HIGH: Wrapping RouterProvider inside an auth provider incorrectly

If you use `createRootRouteWithContext<{ auth: AuthState }>()`, the auth state must be available when the router is created — not injected after.

```tsx
// WRONG — router created before auth is available
const router = createRouter({ routeTree, context: {} })

function App() {
const auth = useAuth() // too late
return <RouterProvider router={router} />
}

// CORRECT — provide context at creation time
function App() {
const auth = useAuth()
const router = useMemo(
() => createRouter({ routeTree, context: { auth } }),
[auth],
)
return <RouterProvider router={router} />
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

TanStack Router v1 React authenticated routes RouterProvider context auth createRootRouteWithContext

💡 Result:

To do authenticated routes in TanStack Router v1 (React) using router context, you:

  1. Type the router context at the root with createRootRouteWithContext
  2. Provide a “placeholder” context when creating the router (so TS knows the shape)
  3. Inject the real auth value at runtime via <RouterProvider context={...} />
  4. Gate protected routes with beforeLoad and throw redirect(...)
  5. Invalidate the router when auth changes so beforeLoad/loaders re-run

1) Root route with typed context

// routes/__root.tsx
import { createRootRouteWithContext, Outlet } from '@tanstack/react-router'

export type RouterContext = {
  auth: {
    isAuthenticated: boolean
    user?: { id: string } | null
  }
}

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

This is the canonical pattern for typed router context. [1]

2) Create the router with a placeholder context

// router.ts
import { createRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen'

export const router = createRouter({
  routeTree,
  context: {
    auth: undefined!, // filled in by <RouterProvider />
  },
})

TanStack’s docs show providing an initial/placeholder context in createRouter. [1]

3) Inject auth via RouterProvider (and invalidate on auth change)

// main.tsx / AppShell.tsx
import { RouterProvider, useRouter } from '@tanstack/react-router'
import { router } from './router'

function useAuth() {
  // your auth hook/store
  return { isAuthenticated: false, user: null }
}

function App() {
  const r = useRouter()
  const auth = useAuth()

  // when auth changes, invalidate so route guards/loaders see fresh auth
  // (pattern shown in the docs)
  // useEffect(() => { r.invalidate() }, [auth.isAuthenticated, auth.user?.id])
  // (or call r.invalidate() inside your auth subscription callback)

  return <RouterProvider router={router} context={{ auth }} />
}

TanStack Router docs explicitly recommend router.invalidate() when external state (like auth) changes. [1]

4) Protect a route (or layout “group”) with beforeLoad + redirect

// routes/_authenticated.tsx (file-based layout route) OR any route definition
import { createFileRoute, redirect, Outlet } from '@tanstack/react-router'

export const Route = createFileRoute('/_authenticated')({
  beforeLoad: ({ context, location }) => {
    if (!context.auth.isAuthenticated) {
      throw redirect({
        to: '/login',
        search: { redirect: location.href },
      })
    }
  },
  component: () => <Outlet />,
})
  • beforeLoad runs before the route loads and can block/redirect navigation. [2]
  • redirect() can be thrown from beforeLoad/loader to navigate away. [3]

Key gotcha: don’t rely on a React context/hook inside beforeLoad—instead, pass the hook result through the router context (because hooks can’t run in beforeLoad). [1]

Sources:
[1] TanStack Router Docs – Router Context (typed context, RouterProvider injection, invalidation) https://tanstack.com/router/latest/docs/guide/router-context
[2] TanStack Router Docs – Data Loading (role of beforeLoad and context merging) https://tanstack.dev/router/latest/docs/framework/react/guide/data-loading
[3] TanStack Router Docs – redirect function (throw/return redirect from beforeLoad/loader) https://zh-hans.tanstack.dev/router/latest/docs/framework/react/api/router/redirectFunction


Use RouterProvider's context prop for auth instead of recreating the router.

TanStack Router's canonical React pattern creates the router once with a placeholder context ({ auth: undefined! }), then injects the live auth value through <RouterProvider context={{ auth }} />. The "CORRECT" example here recreates the router in useMemo whenever auth changes, which contradicts the official API and will steer agents toward unnecessary complexity.

Suggested fix
-If you use `createRootRouteWithContext<{ auth: AuthState }>()`, the auth state must be available when the router is created — not injected after.
+If you use `createRootRouteWithContext<{ auth: AuthState }>()`, keep the router instance stable and pass the current auth state through `RouterProvider`'s `context` prop.

 ```tsx
-// WRONG — router created before auth is available
-const router = createRouter({ routeTree, context: {} })
+// WRONG — auth is never passed into router context
+const router = createRouter({
+  routeTree,
+  context: { auth: undefined! },
+})

 function App() {
-  const auth = useAuth() // too late
   return <RouterProvider router={router} />
 }

-// CORRECT — provide context at creation time
-function App() {
+// CORRECT — inject auth through RouterProvider
+const router = createRouter({
+  routeTree,
+  context: { auth: undefined! },
+})
+
+function InnerApp() {
   const auth = useAuth()
-  const router = useMemo(
-    () => createRouter({ routeTree, context: { auth } }),
-    [auth],
-  )
-  return <RouterProvider router={router} />
+  return <RouterProvider router={router} context={{ auth }} />
+}
+
+function App() {
+  return (
+    <AuthProvider>
+      <InnerApp />
+    </AuthProvider>
+  )
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/react-router/skills/react-router/SKILL.md` around lines 451 - 472,
The example incorrectly recreates the router with changing auth (useMemo)
instead of creating the router once with a placeholder context and injecting the
live auth via RouterProvider; update the code so createRouter({ routeTree,
context: { auth: undefined! } }) is called once (e.g., at module scope or
top-level of App), remove the useMemo recreation in App, create an InnerApp that
calls useAuth(), and render <RouterProvider router={router} context={{ auth }}
/> inside that InnerApp, wrapping InnerApp with your AuthProvider in App.

Comment on lines +107 to +115
// src/routes/dashboard.tsx
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/dashboard')({
beforeLoad: ({ context }) => {
// context.auth is already typed as { userId: string; role: 'admin' | 'user' } | null
// NO annotation needed
if (!context.auth) throw redirect({ to: '/login' })
return { user: context.auth }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Import redirect in this route example.

beforeLoad throws redirect(...), but the snippet only imports createFileRoute. As written, this example is incomplete for copy/paste and teaches an invalid route module.

🩹 Proposed fix
- import { createFileRoute } from '@tanstack/react-router'
+ import { createFileRoute, redirect } from '@tanstack/react-router'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// src/routes/dashboard.tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/dashboard')({
beforeLoad: ({ context }) => {
// context.auth is already typed as { userId: string; role: 'admin' | 'user' } | null
// NO annotation needed
if (!context.auth) throw redirect({ to: '/login' })
return { user: context.auth }
// src/routes/dashboard.tsx
import { createFileRoute, redirect } from '@tanstack/react-router'
export const Route = createFileRoute('/dashboard')({
beforeLoad: ({ context }) => {
// context.auth is already typed as { userId: string; role: 'admin' | 'user' } | null
// NO annotation needed
if (!context.auth) throw redirect({ to: '/login' })
return { user: context.auth }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/router-core/skills/router-core/type-safety/SKILL.md` around lines
107 - 115, The route example throws redirect(...) in beforeLoad but never
imports redirect, making the snippet invalid; update the top import to include
redirect alongside createFileRoute (e.g., import { createFileRoute, redirect }
from '@tanstack/react-router') so Route's beforeLoad can call redirect; ensure
the symbol names referenced are createFileRoute, redirect, and beforeLoad in the
Route definition.

Comment on lines +252 to +266
```tsx
import type { LinkProps } from '@tanstack/react-router'

// WRONG — LinkProps is a massive union, extremely slow TS check
const props: LinkProps = { to: '/posts' }

// CORRECT — infer a precise type, validate against LinkProps
const props = { to: '/posts' } as const satisfies LinkProps

// EVEN BETTER — narrow LinkProps with generic params
import type { RegisteredRouter } from '@tanstack/react-router'
const props = {
to: '/posts',
} as const satisfies LinkProps<RegisteredRouter, string, '/posts'>
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Split the LinkProps variants into separate snippets or make each variant self-contained.

This fence is not valid TypeScript as written: it redeclares const props multiple times and adds an import after statements on Line 262. For an AI-skill doc, that makes the "better" pattern harder to extract correctly.

🩹 Proposed fix
 import type { LinkProps } from '@tanstack/react-router'
+import type { RegisteredRouter } from '@tanstack/react-router'

 // WRONG — LinkProps is a massive union, extremely slow TS check
-const props: LinkProps = { to: '/posts' }
+const wrongProps: LinkProps = { to: '/posts' }

 // CORRECT — infer a precise type, validate against LinkProps
-const props = { to: '/posts' } as const satisfies LinkProps
+const goodProps = { to: '/posts' } as const satisfies LinkProps

 // EVEN BETTER — narrow LinkProps with generic params
-import type { RegisteredRouter } from '@tanstack/react-router'
-const props = {
+const narrowedProps = {
   to: '/posts',
 } as const satisfies LinkProps<RegisteredRouter, string, '/posts'>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/router-core/skills/router-core/type-safety/SKILL.md` around lines
252 - 266, The code fence redeclares `const props` and places an `import` after
statements, producing invalid TypeScript; split into separate, self-contained
snippets so each example compiles independently: (1) show the wrong example with
`import type { LinkProps }` at the top and `const props: LinkProps = { to:
'/posts' }`, (2) show the correct `as const satisfies LinkProps` variant with
its own import if needed, and (3) show the narrowed generic example with `import
type { RegisteredRouter }` (and `LinkProps`) at the top and `const props = { to:
'/posts' } as const satisfies LinkProps<RegisteredRouter, string, '/posts'>`;
ensure no duplicate `const props` in the same snippet and place imports before
usage so each snippet is independently valid.

Comment on lines +8 to +18
} catch (e) {
if (e?.code === 'ERR_MODULE_NOT_FOUND' || e?.code === 'MODULE_NOT_FOUND') {
console.error('@tanstack/intent is not installed.')
console.error('')
console.error('Install it as a dev dependency:')
console.error(' npm add -D @tanstack/intent')
console.error('')
console.error('Or run directly:')
console.error(' npx @tanstack/intent@latest list')
process.exit(1)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n packages/start-server-core/bin/intent.js

Repository: TanStack/router

Length of output: 906


🏁 Script executed:

# Search for similar error handling patterns in the codebase
rg -t js 'ERR_MODULE_NOT_FOUND|MODULE_NOT_FOUND' --context 3

Repository: TanStack/router

Length of output: 5999


Check error messages to distinguish missing @tanstack/intent from its transitive failures.

The catch block treats all ERR_MODULE_NOT_FOUND / MODULE_NOT_FOUND errors as "@tanstack/intent is not installed", but this masks failures in @tanstack/intent's own dependencies. When @tanstack/intent/intent-library exists but one of its imports is missing, users see the wrong remediation. Verify that the error message references the target module before showing the install prompt.

🛠️ Suggested fix
 } catch (e) {
-  if (e?.code === 'ERR_MODULE_NOT_FOUND' || e?.code === 'MODULE_NOT_FOUND') {
+  const isModuleNotFound =
+    e?.code === 'ERR_MODULE_NOT_FOUND' || e?.code === 'MODULE_NOT_FOUND'
+  const missingIntentLibrary =
+    typeof e?.message === 'string' &&
+    e.message.includes('@tanstack/intent/intent-library')
+
+  if (isModuleNotFound && missingIntentLibrary) {
     console.error('@tanstack/intent is not installed.')
     console.error('')
     console.error('Install it as a dev dependency:')
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} catch (e) {
if (e?.code === 'ERR_MODULE_NOT_FOUND' || e?.code === 'MODULE_NOT_FOUND') {
console.error('@tanstack/intent is not installed.')
console.error('')
console.error('Install it as a dev dependency:')
console.error(' npm add -D @tanstack/intent')
console.error('')
console.error('Or run directly:')
console.error(' npx @tanstack/intent@latest list')
process.exit(1)
}
} catch (e) {
const isModuleNotFound =
e?.code === 'ERR_MODULE_NOT_FOUND' || e?.code === 'MODULE_NOT_FOUND'
const missingIntentLibrary =
typeof e?.message === 'string' &&
e.message.includes('@tanstack/intent/intent-library')
if (isModuleNotFound && missingIntentLibrary) {
console.error('@tanstack/intent is not installed.')
console.error('')
console.error('Install it as a dev dependency:')
console.error(' npm add -D `@tanstack/intent`')
console.error('')
console.error('Or run directly:')
console.error(' npx `@tanstack/intent`@latest list')
process.exit(1)
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/start-server-core/bin/intent.js` around lines 8 - 18, The catch
block that currently treats any ERR_MODULE_NOT_FOUND / MODULE_NOT_FOUND as
"@tanstack/intent is not installed" is too broad; update the handler to verify
the missing-module message actually references "@tanstack/intent" (e.g., inspect
e.message or e.requireStack for "Cannot find module '@tanstack/intent'" or the
module name string) before printing the install prompt, otherwise rethrow or
print the original error and exit; modify the catch around the dynamic import
(the try/catch handling e) to check e?.code and
e?.message.includes('@tanstack/intent') (or similar) and only show the
installation/helpful console.error lines and process.exit(1) when the missing
module is indeed `@tanstack/intent`, otherwise surface the real error.

Comment on lines +20 to +22
> **CRITICAL**: These utilities are SERVER-ONLY. Import them from `@tanstack/<framework>-start/server`, not from the main entry point. They throw if called outside a server request context.

> **CRITICAL**: Types are FULLY INFERRED. Never cast, never annotate inferred values.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix the blockquote blank line here.

Line 21 still trips markdownlint MD028, so this new skill file will fail lint as-is.

🧹 Suggested fix
 > **CRITICAL**: These utilities are SERVER-ONLY. Import them from `@tanstack/<framework>-start/server`, not from the main entry point. They throw if called outside a server request context.
-
+>
 > **CRITICAL**: Types are FULLY INFERRED. Never cast, never annotate inferred values.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
> **CRITICAL**: These utilities are SERVER-ONLY. Import them from `@tanstack/<framework>-start/server`, not from the main entry point. They throw if called outside a server request context.
> **CRITICAL**: Types are FULLY INFERRED. Never cast, never annotate inferred values.
> **CRITICAL**: These utilities are SERVER-ONLY. Import them from `@tanstack/<framework>-start/server`, not from the main entry point. They throw if called outside a server request context.
>
> **CRITICAL**: Types are FULLY INFERRED. Never cast, never annotate inferred values.
🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 21-21: Blank line inside blockquote

(MD028, no-blanks-blockquote)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/start-server-core/skills/start-server-core/SKILL.md` around lines 20
- 22, The two consecutive blockquote paragraphs in SKILL.md (the lines starting
with "**CRITICAL**: These utilities are SERVER-ONLY..." and "**CRITICAL**: Types
are FULLY INFERRED...") currently have an extra blank line that trips
markdownlint MD028; remove the empty line between those blockquote lines (or
merge them into a single contiguous blockquote) so there is no blank line inside
the blockquote, preserving the existing wording and punctuation.

Comment on lines +53 to +64
```ts
import {
getRequest,
getRequestHeaders,
getRequestHeader,
getRequestIP,
getRequestHost,
getRequestUrl,
getRequestProtocol,
} from '@tanstack/react-start/server'

const serverFn = createServerFn({ method: 'GET' }).handler(async () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Locate the skill file
find . -name "SKILL.md" -path "*/start-server-core/skills/*" 2>/dev/null | head -20

Repository: TanStack/router

Length of output: 121


🏁 Script executed:

# If found, check the file size and examine the relevant sections
if [ -f "packages/start-server-core/skills/start-server-core/SKILL.md" ]; then
  echo "=== File found ===" 
  wc -l "packages/start-server-core/skills/start-server-core/SKILL.md"
  echo ""
  echo "=== Lines 50-70 ==="
  sed -n '50,70p' "packages/start-server-core/skills/start-server-core/SKILL.md"
  echo ""
  echo "=== Lines 75-95 ==="
  sed -n '75,95p' "packages/start-server-core/skills/start-server-core/SKILL.md"
  echo ""
  echo "=== Lines 100-115 ==="
  sed -n '100,115p' "packages/start-server-core/skills/start-server-core/SKILL.md"
  echo ""
  echo "=== Lines 140-155 ==="
  sed -n '140,155p' "packages/start-server-core/skills/start-server-core/SKILL.md"
  echo ""
  echo "=== Lines 155-165 ==="
  sed -n '155,165p' "packages/start-server-core/skills/start-server-core/SKILL.md"
  echo ""
  echo "=== Lines 185-195 ==="
  sed -n '185,195p' "packages/start-server-core/skills/start-server-core/SKILL.md"
fi

Repository: TanStack/router

Length of output: 2566


🏁 Script executed:

# Search for all occurrences of createServerFn in the file to understand context
if [ -f "packages/start-server-core/skills/start-server-core/SKILL.md" ]; then
  rg "createServerFn" "packages/start-server-core/skills/start-server-core/SKILL.md" -n
fi

Repository: TanStack/router

Length of output: 706


🏁 Script executed:

# Check package.json to verify the correct import path for createServerFn
rg "createServerFn" packages/start-client-core/ packages/start-server-core/ -l --type ts | head -10

Repository: TanStack/router

Length of output: 377


🏁 Script executed:

# Examine broader context to see if these are separate code blocks
sed -n '65,80p' "packages/start-server-core/skills/start-server-core/SKILL.md"

Repository: TanStack/router

Length of output: 404


🏁 Script executed:

# Check structure around line 80-105 to see block boundaries
sed -n '90,105p' "packages/start-server-core/skills/start-server-core/SKILL.md"

Repository: TanStack/router

Length of output: 355


🏁 Script executed:

# Check around line 140-160 for session code block
sed -n '135,165p' "packages/start-server-core/skills/start-server-core/SKILL.md"

Repository: TanStack/router

Length of output: 856


Import createServerFn in code snippets that call it.

Each of these separate code blocks uses createServerFn(...) but lacks the necessary import statement. Skill files must contain self-contained, copy-pasteable examples. Add import { createServerFn } from '@tanstack/react-start' to every snippet that calls createServerFn, or explicitly mark the import as intentionally omitted.

Affected snippets: lines 53–70, 80–98, 103–115, 140–161, 185–195.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/start-server-core/skills/start-server-core/SKILL.md` around lines 53
- 64, Several markdown code blocks in SKILL.md call createServerFn but omit its
import; update every snippet that invokes createServerFn (the blocks showing
serverFn = createServerFn({...}).handler(...)) to include the missing import
statement: add import { createServerFn } from '@tanstack/react-start' at the top
of each of those code fences so each example is self-contained and
copy-pasteable.

Comment on lines +304 to +315
```vue
// SFC template (most common for user code) // MyRoute.component.vue
<template>
<div>{{ data.title }}</div>
</template>

<script setup>
import { useLoaderData } from '@tanstack/vue-router'
const data = useLoaderData({ from: '/posts/$postId' })
</script>
```

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Invalid comment syntax in Vue SFC example.

Line 305 has JavaScript-style comments (// SFC template...) outside any <script> block. In Vue SFC files, // comments are only valid inside <script> sections—this would cause a syntax error if copied directly.

Proposed fix: move comment to markdown or use HTML comment
 ```vue
-// SFC template (most common for user code) // MyRoute.component.vue
+<!-- MyRoute.component.vue - SFC template (most common for user code) -->
 <template>
   <div>{{ data.title }}</div>
 </template>

Alternatively, place the description above the code block in markdown:

+SFC template (most common for user code) in `MyRoute.component.vue`:
+
 ```vue
-// SFC template (most common for user code) // MyRoute.component.vue
 <template>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/vue-router/skills/vue-router/SKILL.md` around lines 304 - 315, The
Vue SFC example includes JavaScript-style comments outside a <script> block (the
"// SFC template... MyRoute.component.vue" line) which will break if copied into
an .vue file; replace that leading // comment with an HTML comment (e.g., <!--
MyRoute.component.vue - SFC template -->) or move the explanatory text above the
code block in markdown, leaving the <template> and <script setup> (and the
useLoaderData/data usage) intact.

@codspeed-hq
Copy link

codspeed-hq bot commented Mar 9, 2026

Merging this PR will not alter performance

✅ 6 untouched benchmarks


Comparing feat/tanstack-intent-skills (ec661f4) with main (31ed0a9)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (6438c03) during the generation of this report, so 31ed0a9 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

Comment on lines +200 to +201
// ensureQueryData returns cached data if fresh, fetches if stale
return context.queryClient.ensureQueryData(postsQueryOptions)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think ensureQueryData "fetches if stale". I think it's just "fetch if not at all in cache". For "fetch if stale" you need

return context.queryClient.ensureQueryData({...postsQueryOptions, revalidateIfStale: true})


return (
<ul>
{posts.map((post: any) => (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't encourage any, right? But also queryFn: () => fetch('/api/posts').then((r) => r.json()), will be any so maybe for the sake of the example it's ok.

```tsx
const { postId } = Route.useParams()
```

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to add a section on "how to replace useLocation" because i think most react-router apps rely on this hook heavily, and when they see tanstack/router has one with the same name they assume it can be used the same. (See issue: #3110)

useLocation is about the "live" URL, what you care about is most likely "what is currently rendered":

  • the routes => useMatch, useMatches, useChildMatches, useParentMatches
  • the params => useParams, useSearch

Comment on lines +464 to +471
// CORRECT — provide context at creation time
function App() {
const auth = useAuth()
const router = useMemo(
() => createRouter({ routeTree, context: { auth } }),
[auth],
)
return <RouterProvider router={router} />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't that a risky pattern? If auth changes, the router is re-created, which resets caches, rebuilds the tree, ...

<Await promise={deferredData}>{(data) => <div>{data}</div>}</Await>
</Suspense>
```

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

idk where we should put this, but a question i've seen come up a bunch was "how to create a reusable component that contains tanstack router hooks?". I had a hard time finding a nice pattern until Manuel showed me this one:

function MyComponent({ from }: { from: '/a/$id' | '/b/$id' }) {
	const { id } = useParams({ from })
	// ...
}

})
}
},
component: () => <Outlet />,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

component defaults to Outlet, should we still declare it anyway to be explicit / avoid surprises?

Comment on lines +114 to +117
function InnerApp() {
const auth = useAuth()
return <RouterProvider router={router} context={{ auth }} />
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not the same pattern as packages/react-router/skills/react-router/SKILL.md so it might be confusing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants