| name | tanstack-start |
| description | Complete TanStack Start execution playbook. Use when implementing routes, route loading/data-fetching flows, server functions, middleware/auth, mutations/invalidation, SSR boundaries, and production readiness checks. |
TanStack Start
Use this skill to implement TanStack Start features with consistent patterns in this repository.
1) Start with task classification
Choose one primary lane before coding:
- Route lane: file route shape, params/search validation, loaders, pending/error boundaries.
- Fetch lane: loader-only fetch vs TanStack Query integration for cache-aware behavior.
- Server lane: server function contract, input validation, middleware, auth/authorization.
- Mutation lane: write path + invalidation/reload strategy after writes.
- Runtime lane: SSR/client execution boundaries, secrets, production checks.
Always preserve end-to-end type flow across params, search, loader data, and server-function input/output.
2) Route loading pattern (default)
When data is required to render a route, start with a route loader.
Implementation checklist:
- Use
createFileRoute(...).
- Validate route params/search in route options before loading.
- Put route-level fetch in
loader.
- Configure freshness:
staleTime: freshness window
gcTime: inactive cache retention
- Keep loader data normalized and minimal for UI.
Use this lane when route navigation should naturally drive reload behavior.
3) Data fetching pattern selection
Pick one of these deliberately:
- Loader-only: Route-owned read data; simplest mental model.
- Loader + Query: When you need richer cache controls, background refresh, or shared query cache beyond one route.
- Client-only fetch: Only for non-critical or progressive enhancement data; do not block core route rendering on ad-hoc effects.
Rules:
- Do not duplicate the same fetch in both loader and component effect.
- If mutation affects loader data, call router invalidation after success.
- Keep a single source of truth for a resource per route.
4) Server function pattern (read + write)
Server functions are the canonical typed RPC boundary.
For each server function:
- Define method with
createServerFn({ method: "GET" | "POST" | ... }).
- Validate input at boundary (Zod validator pattern).
- Compose middleware for auth/context/logging concerns.
- Keep handler business-focused and deterministic.
- Return typed serializable output only.
Apply to both read and write paths; do not move privileged logic into client code.
5) Middleware architecture
Middleware applies to both server routes and server functions and is composable.
Use middleware for:
- authentication and authorization
- request/response logging
- cross-cutting context injection
- consistent error shaping
Important boundary:
- Route
beforeLoad protects UX navigation only.
- Server-function middleware protects the actual RPC endpoint.
- For protected operations, you usually need both.
Design guidance:
- Request middleware: global or route-level server request behavior.
- Function middleware: server-function-specific client/server wrapping plus input validation chain.
- Keep middlewares small and composable; use factories for permission-specific variants.
6) Mutation + invalidation pattern
After successful writes:
- Return minimal confirmation/payload from server function.
- Invalidate affected route matches (router invalidate flow).
- Let route loaders rehydrate canonical state.
Prefer invalidation over manual local patching when correctness matters more than micro-optimization.
7) Error and pending UX pattern
Each touched route should have:
- clear pending UI behavior while loader resolves
- clear error boundary behavior for loader/server-function failures
- predictable empty-state rendering for valid-but-empty data
Do not swallow server-function errors in middleware unless rethrowing a structured equivalent.
8) SSR/client execution safety
TanStack Start loaders are isomorphic. Do not assume loader code runs only on server.
Production-safe rules:
- Keep secrets in server-only execution paths (
createServerFn / server-only helpers).
- Avoid importing server-only modules into client-executed paths.
- Validate environment variable usage by execution context.
- Confirm no secret-bearing code leaks into client bundle.
9) Practical anti-patterns to avoid
- Fetching critical route data in
useEffect instead of loader.
- Putting authorization only in
beforeLoad and not in server-function middleware.
- Returning oversized, unstable objects from loaders.
- Duplicating validation logic inconsistently across client and server.
- Updating UI after mutation without invalidating affected route data.
Commands
Use Bun-first commands in this repo:
bun install
bun run dev
bun run lint
bun test
10) Done definition for TanStack Start work
Before marking complete:
- Route navigation + pending/error behavior verified.
- Loader freshness tuned intentionally (
staleTime/gcTime) or defaults justified.
- Server function boundary validated (input + auth + typed result).
- Mutation path invalidates/reloads affected data.
- SSR/client boundary checked for secret leakage risk.
bun run lint and bun test pass for touched scope.
References and deep dives