tanstack-start — правило для Cursor: что делает и как установить
Инструктирует Cursor по архитектуре TanStack Start: серверным функциям createServerFn, стримингу через defer() и конфигурации Vinxi. Помогает писать типизированный фулстек-код без лишних REST API.
.cursor/rules/tanstack-start.mdcЧто делает tanstack-start
Правило задаёт для Cursor стандарты работы с TanStack Start — связкой TanStack Router и Vinxi (Vite плюс Nitro). Оно применяется к файлам src/routes/**/*, src/server/**/* и app.config.ts, поэтому агент не станет придумывать стандартные REST-эндпоинты там, где уместнее createServerFn с валидацией через Zod.
Внутри собраны готовые шаблоны для корневого макета __root.tsx, серверных мутаций, сырых HTTP-обработчиков createAPIFileRoute для вебхуков и стриминга данных. Неприоритетные данные выносятся в defer() с обёрткой в <Await> и Suspense. Для деплоя задаются пресеты сервера: node-server, vercel, netlify, bun или cloudflare-pages.
В коде действует строгое разделение переменных окружения. Любое прямое обращение к process.env в клиентском компоненте сломает сборку, так как эти переменные разрешены только внутри серверных функций.
Какие задачи решает
- настроить серверные функции createServerFn со сквозной типизацией
- организовать отложенную загрузку данных через defer() и Suspense
- сконфигурировать серверный пресет в app.config.ts под платформу деплоя
- объявить маршрут для вебхука через createAPIFileRoute
Примеры запросов агенту
- Напиши серверную функцию для создания статьи с валидацией входных данных через Zod
- Добавь маршрут
/posts/$postIdсо стримингом комментариев через defer() - Настрой app.config.ts с пресетом для деплоя на cloudflare-pages
Как установить tanstack-start
Вручную: положить файлы
.cursor/rules/tanstack-start.mdcВо frontmatter: description, globs, alwaysApply
Вручную: положить файлы
.claude/rules/tanstack-start.mdПоле paths во frontmatter ограничивает файлы: globs из источника → paths
AGENTS.md
Codex читает AGENTS.md: вставьте текст правила туда
Вручную: положить файлы
.github/instructions/tanstack-start.instructions.mdПоле applyTo задаёт, к каким файлам применять: globs из источника → applyTo
Вручную: положить файлы
.devin/rules/tanstack-start.mdВручную: положить файлы
.clinerules/tanstack-start.mdПо шагам, с командами для каждой платформы: Cursor rules: файлы .mdc, четыре режима и замена .cursorrules
Вопросы о tanstack-start
Как установить tanstack-start в Cursor?
Создайте файл .cursor/rules/tanstack-start.mdc в корне проекта и вставьте в него текст правила. После этого Cursor будет применять правила к файлам маршрутов, сервера и конфигурации.
Зачем нужно это правило?
Оно обучает модель особенностям TanStack Start: замене REST API на createServerFn, правильной работе с app.config.ts и организации файлового роутинга TanStack Router.
Как по правилу передавать переменные окружения?
Серверные переменные доступны через process.env исключительно внутри серверных функций. Для клиентского кода используются только переменные с префиксом import.meta.env.VITE_*.
Исходный текст
tanstack-start.mdc · CC0-1.0
---
description: "TanStack Start full-stack React framework using server functions, API routes, SSR, streaming with defer(), and multi-platform deployment via Vinxi/Nitro"
globs: ["src/routes/**/*", "src/server/**/*", "app.config.ts"]
alwaysApply: false
---
You are an expert in TanStack Start, TanStack Router, React, TypeScript, and full-stack type-safe web applications.
## Core Principles
- TanStack Start = TanStack Router + Vinxi (Vite + Nitro) for full-stack React
- `createServerFn` is the primary way to run server-side logic with end-to-end type safety
- All TanStack Router conventions apply — file-based routing, loaders, search params, etc.
- Server functions replace REST endpoints for most use cases
- Streaming + Suspense are first-class — use `defer()` for non-critical data
## 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 HTML Shell
```tsx
// src/routes/__root.tsx
export const Route = createRootRoute({
component: () => (
<html lang="en">
<head />
<body>
<Outlet />
<ScrollRestoration />
<Scripts />
</body>
</html>
),
})
```
## Server Functions
```ts
// src/server/functions/posts.ts
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 }) => db.post.create({ data }))
```
## Using Server Functions in Routes
```tsx
export const Route = createFileRoute('/posts/$postId')({
loader: ({ params }) => getPost({ data: { id: params.postId } }),
component: PostDetail,
})
```
## Mutations with Server Functions
```tsx
const mutation = useMutation({
mutationFn: (input: { title: string; body: string }) => createPost({ data: input }),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['posts'] }),
})
```
## API Routes (for webhooks / raw HTTP)
```ts
// src/routes/api/webhook.ts
export const Route = createAPIFileRoute('/api/webhook')({
POST: async ({ request }) => {
const body = await request.json()
return Response.json({ received: true })
},
})
```
## Streaming with defer()
```tsx
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
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}>{(c) => <CommentsList comments={c} />}</Await>
</Suspense>
</div>
)
}
```
## Environment Variables
- Access server-only vars via `process.env` inside server functions only
- Use `import.meta.env.VITE_*` for client-exposed variables
- Never access `process.env` in client components
## Deployment Targets
Configure `server.preset` in `app.config.ts`:
- `node-server` — default Node.js
- `vercel` — Vercel serverless/edge
- `netlify` — Netlify Functions
- `bun` — Bun runtime
- `cloudflare-pages` — Cloudflare Pages + Workers
© PatrickJS · CC0-1.0 · PatrickJS/awesome-cursorrules