tanstack-start

TanStack Start full-stack React framework. Use for: server functions with createServerFn, TanStack Router file-based routing, TanStack Query SSR integration, Cloudflare Workers deployment.

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" with this command: npx skills add ferdousbhai/tanstack-start-skill/ferdousbhai-tanstack-start-skill-tanstack-start

TanStack Start

Full-stack React framework with SSR, server functions, and Vite bundling.

Project Setup

New project:

pnpm create cloudflare@latest my-app --framework=tanstack-start -y --no-deploy

Existing app: See references/migration.md for converting React/Vite apps.

Critical Configuration

vite.config.ts

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
  ],
})

tsconfig.json gotcha

Do NOT enable verbatimModuleSyntax - it leaks server bundles into client bundles.

Server Functions

See references/server-functions.md for complete guide.

⚠️ Critical: Route loaders run on server for initial SSR, but run on CLIENT during navigation. Always wrap server code in createServerFn() to ensure it runs server-side.

When to use what (Cloudflare Workers):

Use CaseSolution
Server code in route loaderscreateServerFn()
Server code from client event handlersAPI routes (server.handlers) work best
Access Cloudflare bindingsimport { env } from 'cloudflare:workers'

createServerFn - for loaders:

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

export const getData = createServerFn().handler(async () => {
  return { data: process.env.SECRET }  // Server-only
})

API routes - for client event handlers:

// routes/api/users.ts
export const Route = createFileRoute('/api/users')({
  server: {
    handlers: {
      POST: async ({ request }) => {
        const body = await request.json()
        return Response.json(await db.users.create(body))
      },
    },
  },
})

// In component: fetch('/api/users', { method: 'POST', body: JSON.stringify(data) })

Key APIs:

  • createServerFn() - Server-only functions for loaders
  • server.handlers - API routes for client event handlers
  • createMiddleware({ type: 'function' }) - Reusable middleware
  • @tanstack/react-start/server: getRequestHeaders(), setResponseHeader(), getCookies()

Routing

See references/routing.md for complete patterns.

File conventions in src/routes/:

PatternRoute
index.tsx/
posts.$postId.tsx/posts/:postId
_layout.tsxLayout (no URL)
__root.tsxRoot layout (required)
import { createFileRoute } from '@tanstack/react-router'
import { createServerFn } from '@tanstack/react-start'

const getPost = createServerFn()
  .handler(async () => await db.post.findFirst())

export const Route = createFileRoute('/posts/$postId')({
  loader: ({ params }) => getPost({ data: params.postId }),
  component: () => {
    const post = Route.useLoaderData()
    return <h1>{post.title}</h1>
  },
})

Cloudflare Deployment

See references/cloudflare-deployment.md for complete guide.

pnpm add -D @cloudflare/vite-plugin wrangler

vite.config.ts - add cloudflare plugin:

import { cloudflare } from '@cloudflare/vite-plugin'
// Add to plugins: cloudflare({ viteEnvironment: { name: 'ssr' } })

wrangler.jsonc:

{
  "$schema": "./node_modules/wrangler/config-schema.json",
  "name": "my-app",
  "compatibility_date": "<CURRENT_DATE>",  // Use today's YYYY-MM-DD
  "compatibility_flags": ["nodejs_compat"],
  "main": "@tanstack/react-start/server-entry",
  "observability": { "enabled": true }
}

Access Cloudflare bindings in server functions:

import { env } from 'cloudflare:workers'
const value = await env.MY_KV.get('key')

Static Prerendering (v1.138.0+):

tanstackStart({ prerender: { enabled: true } })

TanStack Query Integration

See references/query-integration.md for SSR setup.

pnpm add @tanstack/react-query @tanstack/react-router-ssr-query
// Preload in loaders, consume with useSuspenseQuery
loader: ({ context }) => context.queryClient.ensureQueryData(myQueryOptions)

Better-Auth Integration

See references/better-auth.md for complete guide.

⚠️ Critical: Use createFileRoute with server.handlers, NOT the legacy createAPIFileRoute.

Mount the auth handler at /src/routes/api/auth/$.ts:

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

export const Route = createFileRoute('/api/auth/$')({
  server: {
    handlers: {
      GET: ({ request }) => auth.handler(request),
      POST: ({ request }) => auth.handler(request),
    },
  },
})

Auth config with tanstackStartCookies plugin:

import { betterAuth } from "better-auth"
import { tanstackStartCookies } from "better-auth/tanstack-start"

export const auth = betterAuth({
  // ...your config
  plugins: [tanstackStartCookies()] // MUST be last plugin
})

Protect routes with middleware:

import { createMiddleware } from "@tanstack/react-start"
import { getRequestHeaders } from "@tanstack/react-start/server"
import { auth } from "./auth"

export const authMiddleware = createMiddleware().server(
  async ({ next }) => {
    const session = await auth.api.getSession({ headers: getRequestHeaders() })
    if (!session) throw redirect({ to: "/login" })
    return next()
  }
)

// In route:
export const Route = createFileRoute('/dashboard')({
  server: { middleware: [authMiddleware] },
  component: Dashboard,
})

GitHub Actions Auto-Deploy

See references/github-actions-deploy.md for CI/CD setup with preview deployments.

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.

General

modal-deployment

No summary provided by upstream source.

Repository SourceNeeds Review
General

tanstack start

No summary provided by upstream source.

Repository SourceNeeds Review
255-jezweb
General

tanstack-start

No summary provided by upstream source.

Repository SourceNeeds Review
General

tanstack start

No summary provided by upstream source.

Repository SourceNeeds Review