TanStack Start Architecture
Portable house style for TanStack Start (@tanstack/react-start) apps. Use this
skill alone — it does not depend on other skills.
Job: where UI, hooks, and feature code live; folder/file naming; ownership.
Not this skill: Start/Router API quirks, SSR adapters, deployment, or latest
framework docs. Prefer current TanStack Start / Router docs for those. Official
Start docs still describe the framework as a Release Candidate (API considered
stable; not bug-free). Prefer npm latest of @tanstack/react-start +
@tanstack/react-router over stale “alpha” labels elsewhere.
If the target repo already documents architecture (e.g. AGENTS.md) and it
conflicts, repo wins unless the user asks to migrate toward this skill.
Stack defaults (core)
| Piece | Default |
|---|---|
| Framework | TanStack Start + file-based TanStack Router (Vite or Rsbuild) |
| Entrypoints | src/router.tsx (getRouter), routes/__root.tsx, generated routeTree.gen.ts; optional start.ts / server.ts |
| Pages | Folder + index.tsx per page (no flat page leaves) |
| Route-only code | Hyphen-prefixed colocated folders (-components, -hooks, -lib) |
| Reusable features | src/modules/<feature>/ after a reuse gate |
| App-wide UI | src/components/ |
| Non-feature infra | src/lib/ |
| Ignore prefix | Router routeFileIgnorePrefix default - |
Load matching with-* extensions when those stacks are present (see below).
Modes
- Scaffold — new page/layout/feature from checklist.md + tree.md.
- Apply — place new UI/hooks/helpers in the canonical spots.
- Review — compare to rules.md; propose moves; do not invent a parallel layout.
Hard rules (core)
- Every page is
segment/index.tsx. Do not add flat page leaves (billing.tsxas the page component file). Preferbilling/index.tsx. - Route-only modules use a
-prefix (or the app’s configured ignore prefix). Unprefixed files undersrc/routesbecome URLs. - Default new page UI to
routes/…/-components. Same for page-only hooks (-hooks) and helpers (-lib). - Reuse gate for
src/modules/<feature>/: promote when a second consumer appears, or for clearly shared clients/schemas used across routes. Do not pre-create empty module trees. - Modules must not import from
src/routes. Routes may import modules. - No module barrel
index.tsby default. Import concrete paths (@/modules/billing/hooks/use-checkout). - App-wide toolkit →
src/components/; non-feature infra →src/lib/. Do not dump random shared UI intoroutes/. - Pathless layouts use
_name/(or_name.tsx) when wrapping a section without changing the URL. - Naming: folder = noun/route segment; leaf = short aspect (
billing-page.tsx,use-checkout.ts). Do not repeat parent path noise in every filename when the folder already carries it. - One job per route folder: that segment’s page/layout and its colocated private code only.
Details: rules.md, tree.md, examples.md.
Progressive disclosure
| Need | Read |
|---|---|
| Canonical trees + tokens | references/tree.md |
| Enforce rules + anti-patterns | references/rules.md |
| Scaffold / review checklists | references/checklist.md |
| Good vs bad layouts | references/examples.md |
| Optional stack overlays | Extensions below |
Extensions
Load an extension only when the matching stack is present (or the user asks). Extensions add rules; they do not replace the core tree.
| When | Extension |
|---|---|
| Generated OpenAPI / Hey-style client | with-generated-api-client.md |
| Better Auth (or session) client module | with-better-auth-client.md |
| TanStack Query + loaders / ensureQueryData | with-tanstack-query.md |
| Pathless auth / onboarding / org gates | with-route-gates.md |
| TanStack Form + module/route schemas | with-tanstack-form.md |
createEnv / VITE_ client keys |
with-env.md |
| Pure authz package + client adapters | with-client-authorization.md |
| Workspace UI package + Storybook/tokens | with-ui-package.md |
| Effect Schema / server-only Effect | with-effect.md |
| Vitest — libs/schemas/gates focus | with-vitest.md |