Tanstack Start
Full-Stack-Konventionen für TanStack Start: SSR, Server-Functions und Deployment-Setup.
Full-Stack-Konventionen für TanStack Start: SSR, Server-Functions und Deployment-Setup.
Original-Beschreibung der Autoren: Cursor rules for TanStack Start full-stack React framework including server functions, API routes, streaming with defer(), SSR, and multi-platform deployment.
Die Regel
---
description: "Cursor rules for TanStack Start full-stack React framework including server functions, API routes, streaming with defer(), SSR, and multi-platform deployment."
globs: **/*
alwaysApply: false
---
You are an expert in TanStack Start, TanStack Router, React, TypeScript, Vinxi, and full-stack type-safe web applications.
# TanStack Start Guidelines
## What is TanStack Start
TanStack Start is a full-stack React framework built on top of TanStack Router and Vinxi (Vite + Nitro). It provides SSR, streaming, server functions, and API routes with end-to-end type safety.
## Core Principles
- TanStack Start is file-based routing via TanStack Router — all routing conventions apply
- Server Functions (`createServerFn`) are the primary way to run server-side logic
- Full-stack type safety: server function inputs/outputs are typed end-to-end
- Streaming and Suspense are first-class — use them for progressive rendering
- Start is NOT an API-first framework — server functions replace REST endpoints for most use cases
## Project Structure
src/ routes/ __root.tsx ← Root layout with HTML shell index.tsx ← Home route posts/ index.tsx $postId.tsx server/ functions/ ← Server functions (recommended organization) posts.ts auth.ts lib/ db.ts ← Database client auth.ts ← Auth utilities app.config.ts ← TanStack Start / Vinxi config
## app.config.ts
```ts
import { defineConfig } from '@tanstack/start/config'
import tsConfigPaths from 'vite-tsconfig-paths'
export default defineConfig({
vite: {
plugins: [tsConfigPaths()],
},
server: {
preset: 'node-server', // or 'vercel', 'netlify', 'bun', 'cloudflare-pages'
},
})
Root Route Setup
// src/routes/__root.tsx
import { createRootRoute, ScrollRestoration, Scripts, Outlet } from '@tanstack/react-router'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import { TanStackRouterDevtools } from '@tanstack/router-devtools'
export const Route = createRootRoute({
component: RootComponent,
})
function RootComponent() {
return (
<html lang="en">
<head />
<body>
<Outlet />
<ScrollRestoration />
<Scripts />
{process.env.NODE_ENV === 'development' && (
<>
<TanStackRouterDevtools />
<ReactQueryDevtools />
</>
)}
</body>
</html>
)
}
Server Functions
- Use
createServerFnto define functions that always run on the server - Validate inputs with Zod using
.validator() - Use
.handler()for the implementation - Server functions are called like regular async functions from components or loaders
// src/server/functions/posts.ts
import { createServerFn } from '@tanstack/start'
import { z } from 'zod'
export const getPost = createServerFn()
.validator(z.object({ id: z.string() }))
.handler(async ({ data }) => {
const post = await db.post.findUnique({ where: { id: data.id } })
if (!post) throw new Error('Post not found')
return post
})
export const createPost = createServerFn()
.validator(z.object({ title: z.string().min(1), body: z.string() }))
.handler(async ({ data, context }) => {
// context has access to request headers, cookies, etc.
return db.post.create({ data })
})
Using Server Functions in Routes
// src/routes/posts/$postId.tsx
import { createFileRoute } from '@tanstack/react-router'
import { getPost } from '../../server/functions/posts'
export const Route = createFileRoute('/posts/$postId')({
loader: ({ params }) => getPost({ data: { id: params.postId } }),
component: PostDetail,
})
function PostDetail() {
const post = Route.useLoaderData()
return <article><h1>{post.title}</h1></article>
}
Mutations with Server Functions
- Call server functions directly in event handlers or via TanStack Query mutations
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { createPost } from '../../server/functions/posts'
function CreatePostForm() {
const queryClient = useQueryClient()
const mutation = useMutation({
mutationFn: (input: { title: string; body: string }) =>
createPost({ data: input }),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['posts'] })
},
})
return (
<form onSubmit={(e) => {
e.preventDefault()
const fd = new FormData(e.currentTarget)
mutation.mutate({ title: fd.get('title') as string, body: fd.get('body') as string })
}}>
<input name="title" />
<textarea name="body" />
<button type="submit" disabled={mutation.isPending}>
{mutation.isPending ? 'Creating...' : 'Create'}
</button>
</form>
)
}
API Routes
- Use
createAPIFileRoutefor raw HTTP endpoints (webhooks, third-party integrations) - Place in
src/routes/api/directory
// src/routes/api/webhook.ts
import { createAPIFileRoute } from '@tanstack/start/api'
export const Route = createAPIFileRoute('/api/webhook')({
POST: async ({ request }) => {
const body = await request.json()
// handle webhook
return Response.json({ received: true })
},
})
Streaming & Suspense
- Use
defer()to stream non-critical data after the initial render - Wrap deferred data consumers in
<Suspense>
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params }) => {
const post = await getPost({ data: { id: params.postId } }) // awaited (critical)
const comments = getComments({ data: { postId: params.postId } }) // not awaited (deferred)
return { post, comments: defer(comments) }
},
component: PostDetail,
})
function PostDetail() {
const { post, comments } = Route.useLoaderData()
return (
<div>
<h1>{post.title}</h1>
<Suspense fallback={<CommentsSkeleton />}>
<Await promise={comments}>
{(resolved) => <C
… (hier gekürzt — Kopieren/Download liefert die vollständige Regel)
So nutzt du sie
Die Regel kopieren (Button oben) oder als Datei herunterladen und im Projekt unter .cursor/rules/ ablegen — Cursor lädt sie beim nächsten Start automatisch. Ältere Cursor-Versionen lesen alternativ eine einzelne .cursorrules-Datei im Projektstamm; dort einfach den Regel-Text ohne den Kopfblock zwischen den ----Zeilen einfügen.
Der Regel-Text ist englisch — Cursor versteht ihn unabhängig von der Sprache, in der Sie mit dem Editor chatten.
Im Detail
TanStack Start ist das Full-Stack-Meta-Framework auf Basis von TanStack Router mit SSR, Streaming und typsicheren Server-Functions als RPC-artige Client/Server-Grenze. Die Regel gibt vor, wie Server-Functions annotiert werden, wie SSR-Loader von Client-only-Code getrennt bleiben und wie Vite-Konfiguration und Deployment-Ziel (Node, Bun, Edge) gehandhabt werden. Interessant für Teams, die eine schlanke Next.js-Alternative mit voller End-to-End-Typsicherheit suchen; da das Framework noch jung ist, lohnt ein Abgleich mit der aktuellen Doku vor blinder Übernahme.
Praxis-Tipp
Gezielt nach „Server-Function für Formular-Submit mit Validierung“ statt nach generischen API-Routen fragen, damit Cursor die Start-spezifische Server-Function-Syntax nutzt.
Lizenz & Quelle
- Lizenz: CC0 1.0
- Quelle: PatrickJS/awesome-cursorrules (GitHub)
Inhalt ansehen (tanstack-start.mdc)
Lade …
Erfahrungen & Kommentare.
Funktioniert der Regel bei Ihnen? Tipps, Stolperfallen, Varianten — teilen Sie es mit der Community.
Lade Kommentare …
Passt dazu.
AI Agent Specialist
Cursor-Regel, die den KI-Editor auf diszipliniertes, spezialisiertes Agenten-Verhalten trimmt.
Alpha Skills Quant Factor Research
Cursor-Regel für quantitative Faktor-Recherche im Trading/Finance-Bereich — leitet die KI zu methodisch sauberer Analyse an.
Android Jetpack Compose
Cursor-Regel für Android-Entwicklung mit Jetpack Compose — sorgt für idiomatischen, deklarativen Kotlin-UI-Code.
