- Read applicable nested
AGENTS.mdfiles before editing or testing a subtree. - Shared routing belongs in
packages/router-core; check React, Solid, and Vue bindings for shared changes. Shared Start runtime/build logic lives inpackages/start-*-core.
- Start bug fixes with a failing regression test that uses only public APIs to reproduce and assert user- or developer-visible behavior. Do not manufacture bugs by mutating internals. Establish whether real usage can reach the failing state before adding runtime handling; simplify handling of states proven unreachable.
- For suspected dependency issues, verify the upstream root cause, then propose an upstream fix to the user, including for other
@tanstack/*packages. Never implement a workaround in this repository unless the user explicitly authorizes it. - During debugging/prototyping, keep fixes aligned with the PR's intended architecture. If making a test pass requires another flag, counter, copied deadline, or duplicate completion authority, stop and consolidate state and ownership. Remove superseded paths instead of accumulating patches and bundle growth.
- Use Node from
.nvmrcand pnpm from rootpackage.json. Install at the root withCI=1 pnpm install --frozen-lockfile. - For sandbox-blocked registry/store access, escalate the same command; report the blocker if unavailable. Do not change stores, delete dependencies/lockfiles, use
--force/--ignore-scripts, or weaken workspace trust/build policies to bypass it. - Never manually edit
pnpm-lock.yamlor anyrouteTree.gen.ts. Regenerate the lockfile withpnpm install --no-frozen-lockfileafter intentional dependency changes; regenerate route trees through app builds/dev servers or the generator fixture harness. - Always use control-flow braces. Run
pnpm formatbefore validation. - Use Nx: workspace imports consume built packages, so direct runners can test stale dependencies. Inspect resolved targets; some are inferred.
CI=1 NX_DAEMON=false pnpm nx run <project>:<target> --outputStyle=stream --skipRemoteCache- Run one Nx command at a time. For a ~20-second startup/graph stall, stop, run
pnpm nx reset, and retry once, then escalate. Do not apply that timeout to running tests. - For code changes, run affected packages'
test:unit,test:types, andtest:eslintwhere available, including affected consumers; usetest:e2efor browser/app behavior andtest:buildfor exports/build changes. Rootpnpm testincludes the full e2e suite. Published-code changes requirepnpm changeset.
- Import
isServerfrom@tanstack/router-core/isServer. Conditional exports select:development→undefined; server (workerd,worker,deno,node,bun) →trueexceptNODE_ENV=test→undefined; browser/fallback →false.developmentwins;NODE_ENV=developmentalone does not select it. - Keep
isServer ?? router.isServerdirectly in each branch condition for dead-code elimination; negate the whole expression for client branches. Never extract it into a variable (e.g.const serverRendering = isServer ?? router.isServer) or helper. Without a router, inlineisServer ?? typeof window === 'undefined'(or the existingdocumentcheck). Keep the constant first and use??, never||. - Never create UI/router reactivity on the server, including development/tests. Branch before reactive setup; use direct reads and core non-reactive stores. Required transport listeners are allowed only with request-scoped lifetimes and cleanup.
- Shared route definitions/build metadata must not acquire request/user data. Keep it on the request's Router, context, or QueryClient.
- HMR can replace code while caches and pending work survive. Invalidate derived state or bypass caching in development; reject stale async results while preserving intentional HMR identities/state.
- Gate developer diagnostics and message construction with direct
process.env.NODE_ENV !== 'production'checks. Preserve required validation/throws in production (e.g. detailed development error, compactinvariant()failure).!== 'development'also enables the guarded code in tests; preserve existing dev-server mode gates.
- For runtime/memory changes, compare identical baseline/candidate workloads using the relevant benchmark guide: client navigation, Start SSR, or memory. Add coverage for unmeasured mechanisms.
- Last phase for every change affecting emitted client JavaScript, including core/build transforms: complete the full bundle-size-optimization skill after correctness and performance validation. The full workflow is mandatory.