tanstack-start-guide

TanStack Start is a full-stack React framework powered by TanStack Router and Vite. It provides SSR, streaming, server functions, server routes, middleware, and universal deployment. If you only need client-side routing without SSR, streaming, server functions, or middleware, use TanStack Router directly instead of Start. Not for Next.js, Remix, or React Router.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "tanstack-start-guide" with this command: npx skills add vcode-sh/vibe-tools/vcode-sh-vibe-tools-tanstack-start-guide

TanStack Start Guide

TanStack Start is a full-stack React framework powered by TanStack Router and Vite. It provides SSR, streaming, server functions, server routes, middleware, and universal deployment. If you only need client-side routing without SSR, streaming, server functions, or middleware, use TanStack Router directly instead of Start. Not for Next.js, Remix, or React Router.

Key differentiators: End-to-end type safety, composable middleware (client + server), selective SSR per route, deployment-agnostic (any Vite-compatible host), explicit over implicit patterns.

RSC support: Available via Composite Components — server-produced React components that the client fetches, caches, and streams. See references/migration.md for details.

Quick Start

pnpm create @tanstack/start@latest

or

npm create @tanstack/start@latest

Or clone an official example:

npx gitpick TanStack/router/tree/main/examples/react/EXAMPLE_SLUG my-project

Official examples: start-basic , start-basic-auth , start-counter , start-basic-react-query , start-clerk-basic , start-convex-trellaux , start-supabase-basic , start-trellaux , start-workos , start-material-ui .

Manual Setup

Install dependencies:

npm i @tanstack/react-start @tanstack/react-router react react-dom npm i -D vite @vitejs/plugin-react typescript vite-tsconfig-paths @types/node @types/react @types/react-dom

Required Files

vite.config.ts — Vite plugin configuration:

import { defineConfig } from 'vite' import tsConfigPaths from 'vite-tsconfig-paths' import { tanstackStart } from '@tanstack/react-start/plugin/vite' import viteReact from '@vitejs/plugin-react'

export default defineConfig({ plugins: [ tsConfigPaths(), tanstackStart(), viteReact(), // MUST come after tanstackStart() ], })

Alternative React plugins: @vitejs/plugin-react-swc or @vitejs/plugin-react-oxc can replace @vitejs/plugin-react .

src/router.tsx — Router configuration:

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

export function getRouter() { return createRouter({ routeTree, scrollRestoration: true }) }

src/routes/__root.tsx — Root route (HTML shell):

/// <reference types="vite/client" /> import type { ReactNode } from 'react' import { Outlet, createRootRoute, HeadContent, Scripts } from '@tanstack/react-router'

export const Route = createRootRoute({ head: () => ({ meta: [ { charSet: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' }, { title: 'My App' }, ], }), component: () => ( <html><head><HeadContent /></head> <body><Outlet /><Scripts /></body> </html> ), })

package.json scripts:

{ "type": "module", "scripts": { "dev": "vite dev", "build": "vite build" } }

Core Workflow

  1. File-Based Routing

Routes live in src/routes/ . The routeTree.gen.ts is auto-generated on dev /build .

Path Filename Type

/

index.tsx

Index

/about

about.tsx

Static

/posts/:id

posts/$postId.tsx

Dynamic

/rest/*

rest/$.tsx

Wildcard

Layout wrapper _layout.tsx

Pathless layout

Grouped dir (group)/route.tsx

Organization only

import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/posts/$postId')({ loader: async ({ params }) => fetchPost(params.postId), component: PostComponent, })

function PostComponent() { const post = Route.useLoaderData() return <h1>{post.title}</h1> }

  1. Server Functions

Server-only logic callable from anywhere. Created with createServerFn() :

import { createServerFn } from '@tanstack/react-start'

export const getUser = createServerFn({ method: 'GET' }) .inputValidator((data: { id: string }) => data) .handler(async ({ data }) => { return await db.users.find(data.id) // Runs only on server })

// Call from loader, component, or other server function const user = await getUser({ data: { id: '123' } })

Validation with Zod:

import { z } from 'zod'

export const createPost = createServerFn({ method: 'POST' }) .inputValidator(z.object({ title: z.string().min(1), body: z.string() })) .handler(async ({ data }) => db.posts.create(data))

Redirects & errors:

import { redirect, notFound } from '@tanstack/react-router'

export const requireAuth = createServerFn().handler(async () => { const user = await getSession() if (!user) throw redirect({ to: '/login' }) return user })

Progressive enhancement (no JS):

// Server functions have a .url property for HTML forms <form method="POST" action={createPost.url}> <input name="title" /> <button type="submit">Create</button> </form>

  1. Middleware

Two types: request middleware (all requests) and server function middleware (server functions only).

import { createMiddleware } from '@tanstack/react-start'

// Request middleware (server only) const logger = createMiddleware().server(async ({ next, request }) => { console.log(request.url) return next() })

// Server function middleware (client + server) const auth = createMiddleware({ type: 'function' }) .client(async ({ next }) => next({ headers: { Authorization: Bearer ${getToken()} } })) .server(async ({ next }) => next({ context: { user: await getUser() } }))

Global middleware via src/start.ts :

import { createStart } from '@tanstack/react-start'

export const startInstance = createStart(() => ({ requestMiddleware: [loggerMiddleware], functionMiddleware: [authMiddleware], }))

  1. Server Routes (API Endpoints)

export const Route = createFileRoute('/api/hello')({ server: { handlers: { GET: async ({ request }) => Response.json({ message: 'Hello!' }), POST: async ({ request }) => { const body = await request.json() return Response.json({ received: body }) }, }, }, })

  1. Sessions

import { useSession } from '@tanstack/react-start/server'

function useAppSession() { return useSession<{ userId?: string }>({ password: process.env.SESSION_SECRET!, cookie: { secure: process.env.NODE_ENV === 'production', httpOnly: true, sameSite: 'lax' }, }) }

Key Rules & Constraints

Loaders are ISOMORPHIC — they run on server during SSR AND on client during navigation. Never access process.env secrets directly in loaders. Use createServerFn() instead.

Environment variables — Server: process.env.ANY_VAR . Client: only import.meta.env.VITE_* prefixed. Never prefix secrets with VITE_ .

Plugin order — tanstackStart() MUST come before viteReact() in vite.config.ts.

TypeScript — Do NOT enable verbatimModuleSyntax (causes server bundle leaking into client). Required settings: jsx: "react-jsx" , moduleResolution: "Bundler" , module: "ESNext" .

Server function imports — Safe to statically import anywhere. Avoid dynamic imports for server functions.

Execution boundaries — Use createServerOnlyFn() for server-only utilities that throw on client. Use createClientOnlyFn() for browser-only utilities. Use createIsomorphicFn() for environment-specific implementations.

Head management — <HeadContent /> in <head> , <Scripts /> at end of <body> . Both required in root route.

Raw Response — Server functions can return Response objects directly for binary data or custom content types.

Error Boundaries

Route-level error boundaries with default + per-route override:

// src/router.tsx — default for all routes export function getRouter() { return createRouter({ routeTree, defaultErrorComponent: ({ error, reset }) => <ErrorComponent error={error} />, }) }

// Per-route override export const Route = createFileRoute('/posts/$postId')({ errorComponent: ({ error, reset }: ErrorComponentProps) => ( <div><p>Error: {error.message}</p><button onClick={reset}>Retry</button></div> ), })

Common Errors

  • Hydration mismatch: Caused by Date.now() , Math.random() , locale-dependent APIs in SSR. Fix: use <ClientOnly> , useHydrated() , or suppressHydrationWarning .

  • Env var undefined on client: Missing VITE_ prefix. Restart dev server after adding new vars.

  • Secret exposed to client: Used process.env in loader (isomorphic!). Move to createServerFn() .

  • Bundle includes server code: Check for accidental dynamic imports of server functions.

Reference Files

  • references/api-routing.md — Routing, createFileRoute, createRootRoute, route hooks, components, error boundaries, navigation

  • references/api-server-functions.md — createServerFn, validation, streaming, server context utilities, useSession, environment functions, useServerFn

  • references/api-middleware.md — createMiddleware, createStart, custom fetch, header merging, fetch override, createHandlers

  • references/server-entry.md — Custom server/client entry, request context, handler callbacks, Cloudflare Workers extensions

  • references/configuration.md — Vite config options, TypeScript, environment variables, path aliases, Tailwind CSS, server build config

  • references/auth-sessions.md — Authentication (DIY + partners), sessions, route protection, RBAC, OAuth, password reset, rate limiting

  • references/data-streaming.md — Data loading patterns, streaming (async generators, ReadableStream), cache control, TanStack Query integration

  • references/seo-llmo.md — SEO meta tags, JSON-LD structured data, LLMO/AIO optimization, sitemaps, robots.txt, llms.txt

  • references/server-routes.md — API endpoints, dynamic params, wildcard routes, request bodies, per-handler middleware, escaped file names

  • references/patterns.md — Markdown rendering, database integration (Neon/Convex/Prisma), file organization, progressive enhancement, execution model, tutorials

  • references/deployment.md — Cloudflare Workers, Netlify, Railway, Vercel, Node.js/Docker, Bun, Appwrite Sites, Nitro

  • references/prerendering-caching.md — Static prerendering (SSG), ISR, selective SSR, SPA mode, CDN asset URLs

  • references/observability.md — Sentry, New Relic, OpenTelemetry, health checks, metrics collection, logging

  • references/migration.md — Next.js migration guide, framework comparison (Start vs Next.js vs React Router)

  • references/troubleshooting.md — Hydration errors, env variable issues, loader mistakes, middleware problems, production checklist

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

orpc-guide

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

tanstack-hotkeys-guide

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

shadcn-guide

No summary provided by upstream source.

Repository SourceNeeds Review