tanstack-start

Full-stack React framework powered by TanStack Router with SSR, streaming, server functions, and deployment to any hosting provider.

9 stars

Best use case

tanstack-start is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Full-stack React framework powered by TanStack Router with SSR, streaming, server functions, and deployment to any hosting provider.

Teams using tanstack-start should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/tanstack-start/SKILL.md --create-dirs "https://raw.githubusercontent.com/sc30gsw/claude-code-customes/main/sample/harness/tanstack-start/skills/tanstack-start/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/tanstack-start/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How tanstack-start Compares

Feature / Agenttanstack-startStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Full-stack React framework powered by TanStack Router with SSR, streaming, server functions, and deployment to any hosting provider.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# TanStack Start Skills

## Overview

TanStack Start is a full-stack React framework built on TanStack Router, powered by Vite and Nitro (via Vinxi). It provides server-side rendering, streaming, server functions (RPC), middleware, API routes, and deploys to any platform via Nitro presets.

**Package:** `@tanstack/react-start`
**Router Plugin:** `@tanstack/router-plugin`
**Build Tool:** Vinxi (Vite + Nitro)
**Status:** RC (Release Candidate)
**RSC Support:** React Server Components support is in active development and will land as a non-breaking v1.x addition

## Installation & Project Setup

```bash
npx @tanstack/cli create my-app
# Or manually:
npm install @tanstack/react-start @tanstack/react-router react react-dom
npm install -D @tanstack/router-plugin typescript vite vite-tsconfig-paths
```

### Project Structure

```
my-app/
  app/
    routes/
      __root.tsx          # Root layout
      index.tsx           # / route
      posts.$postId.tsx   # /posts/:postId
      api/
        users.ts          # /api/users API route
    client.tsx            # Client entry
    router.tsx            # Router creation
    ssr.tsx               # SSR entry
    routeTree.gen.ts      # Auto-generated route tree
  app.config.ts           # TanStack Start config
  tsconfig.json
  package.json
```

### Configuration (`app.config.ts`)

```typescript
import { defineConfig } from "@tanstack/react-start/config";
import viteTsConfigPaths from "vite-tsconfig-paths";

export default defineConfig({
  vite: {
    plugins: [viteTsConfigPaths({ projects: ["./tsconfig.json"] })],
  },
  server: {
    preset: "node-server", // 'vercel' | 'netlify' | 'cloudflare-pages' | etc.
  },
  tsr: {
    appDirectory: "./app",
    routesDirectory: "./app/routes",
    generatedRouteTree: "./app/routeTree.gen.ts",
  },
});
```

## Server Functions (`createServerFn`)

Server functions provide type-safe RPC calls between client and server.

### Basic Server Functions

```typescript
import { createServerFn } from "@tanstack/react-start";

// GET (data fetching, cacheable)
const getUsers = createServerFn().handler(async () => {
  const users = await db.query.users.findMany();
  return users;
});

// POST (mutations, side effects)
const createUser = createServerFn({ method: "POST" })
  .validator((data: { name: string; email: string }) => data)
  .handler(async ({ data }) => {
    const user = await db.insert(users).values(data).returning();
    return user;
  });
```

### With Zod Validation

```typescript
import { z } from "zod";

const updateUser = createServerFn({ method: "POST" })
  .validator(
    z.object({
      id: z.string(),
      name: z.string().min(1),
      email: z.string().email(),
    }),
  )
  .handler(async ({ data }) => {
    // data is fully typed: { id: string; name: string; email: string }
    return await db.update(users).set(data).where(eq(users.id, data.id));
  });
```

## Middleware

### Creating Middleware

```typescript
import { createMiddleware } from "@tanstack/react-start";

const loggingMiddleware = createMiddleware().handler(async ({ next }) => {
  console.log("Request started");
  const result = await next();
  console.log("Request completed");
  return result;
});
```

### Auth Middleware with Context

```typescript
const authMiddleware = createMiddleware().handler(async ({ next }) => {
  const request = getWebRequest();
  const session = await getSession(request);

  if (!session?.user) {
    throw redirect({ to: "/login" });
  }

  // Pass typed context to handler
  return next({ context: { user: session.user } });
});
```

### Chaining Middleware

```typescript
const adminMiddleware = createMiddleware()
  .middleware([authMiddleware])
  .handler(async ({ next, context }) => {
    // context.user is typed from authMiddleware
    if (context.user.role !== "admin") {
      throw redirect({ to: "/unauthorized" });
    }
    return next({ context: { isAdmin: true } });
  });

// Usage
const adminAction = createServerFn({ method: "POST" })
  .middleware([adminMiddleware])
  .handler(async ({ context }) => {
    // context: { user: User; isAdmin: boolean }
    return { success: true };
  });
```

## API Routes (Server Routes)

```typescript
// app/routes/api/users.ts
import { createAPIFileRoute } from "@tanstack/react-start/api";

export const APIRoute = createAPIFileRoute("/api/users")({
  GET: async ({ request }) => {
    const users = await db.query.users.findMany();
    return Response.json(users);
  },
  POST: async ({ request }) => {
    const body = await request.json();
    const user = await db.insert(users).values(body).returning();
    return new Response(JSON.stringify(user), { status: 201 });
  },
});
```

## SSR Strategies

### Streaming SSR (Default)

```typescript
export const Route = createFileRoute('/dashboard')({
  loader: async () => ({
    criticalData: await fetchCriticalData(),
    deferredData: defer(fetchSlowData()),
  }),
  component: Dashboard,
})

function Dashboard() {
  const { criticalData, deferredData } = Route.useLoaderData()
  return (
    <div>
      <CriticalSection data={criticalData} />
      <Suspense fallback={<Loading />}>
        <Await promise={deferredData}>
          {(data) => <SlowSection data={data} />}
        </Await>
      </Suspense>
    </div>
  )
}
```

## Deployment

### Supported Platforms (Nitro Presets)

```typescript
// app.config.ts
export default defineConfig({
  server: {
    preset: "node-server", // Self-hosted Node.js
    // preset: 'vercel',          // Vercel
    // preset: 'netlify',         // Netlify
    // preset: 'cloudflare-pages', // Cloudflare Pages
    // preset: 'aws-lambda',      // AWS Lambda
    // preset: 'deno-server',     // Deno Deploy
    // preset: 'bun',             // Bun
  },
});
```

## Best Practices

1. **Use validators for all server function inputs** - runtime safety and TypeScript inference
2. **Compose middleware** for cross-cutting concerns (auth, logging, rate limiting)
3. **Use `createServerFn` GET** for data fetching (cacheable, preloadable)
4. **Use `createServerFn` POST** for mutations and side effects
5. **Use `beforeLoad`** for route-level auth guards
6. **Use `defer()`** for non-critical data to improve TTFB
7. **Set `defaultPreload: 'intent'`** on the router for instant navigation
8. **Co-locate server functions** with the routes that use them

## Common Pitfalls

- Server functions cannot close over client-side variables (they're extracted to separate bundles)
- Data returned from server functions must be serializable
- Forgetting `await` in loaders leads to streaming issues
- Importing server-only code in client bundles causes build errors
- Missing `declare module '@tanstack/react-router'` loses all type safety

Related Skills

tanstack-start-server-fn-testing

9
from sc30gsw/claude-code-customes

Unit-test TanStack Start createServerFn handlers via a global vi.mock that combines two patterns from Discussion #2701

test

9
from sc30gsw/claude-code-customes

Advanced test implementation command with unit/E2E support, auto-execution, and smart fixing capabilities

serena

9
from sc30gsw/claude-code-customes

Token-efficient Serena MCP command for structured app development and problem-solving

project-guidelines-example

9
from sc30gsw/claude-code-customes

Example project-specific skill template based on a real production application.

notion-bug-pr

9
from sc30gsw/claude-code-customes

Skill that pulls bug tickets (titles containing 「不具合」) from a Notion database, investigates root cause in a GitHub repo, applies fixes, and opens draft PRs. Supports three modes — daily recurring schedule, one-shot at a specific time, or immediate on-demand run. Takes three or four args: Notion database URL, repo path or name, and either HH:MM (daily), "once HH:MM" (one-shot), or "now" (immediate).

graphify

9
from sc30gsw/claude-code-customes

any input (code, docs, papers, images, videos) to knowledge graph. Use when user asks any question about a codebase, documents, or project content - especially if graphify-out/ exists, treat the question as a /graphify query.

chrome

9
from sc30gsw/claude-code-customes

Comprehensive Chrome DevTools development system with native Chrome capabilities for debugging, E2E testing, performance analysis, and browser automation

webapp-testing

9
from sc30gsw/claude-code-customes

Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.

web-design-guidelines

9
from sc30gsw/claude-code-customes

Review UI code for Web Interface Guidelines compliance. Use when asked to "review my UI", "check accessibility", "audit design", "review UX", or "check my site against best practices".

typescript-advanced-types

9
from sc30gsw/claude-code-customes

Master TypeScript's advanced type system including generics, conditional types, mapped types, template literals, and utility types for building type-safe applications. Use when implementing complex type logic, creating reusable type utilities, or ensuring compile-time type safety in TypeScript projects.

tailwind-css-patterns

9
from sc30gsw/claude-code-customes

Provides comprehensive Tailwind CSS utility-first styling patterns including responsive design, layout utilities, flexbox, grid, spacing, typography, colors, and modern CSS best practices. Use when styling React/Vue/Svelte components, building responsive layouts, implementing design systems, or optimizing CSS workflow.

skill-creator

9
from sc30gsw/claude-code-customes

Create new skills, modify and improve existing skills, and measure skill performance. Use when users want to create a skill from scratch, edit, or optimize an existing skill, run evals to test a skill, benchmark skill performance with variance analysis, or optimize a skill's description for better triggering accuracy.