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.
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 |
| 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 |