start-core
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTanStack Start Core
TanStack Start 核心
TanStack Start is a full-stack React framework built on TanStack Router and Vite. It adds SSR, streaming, server functions (type-safe RPCs), middleware, server routes, and universal deployment.
CRITICAL: All code in TanStack Start is ISOMORPHIC by default — it runs in BOTH server and client environments. Loaders run on both server AND client. To run code exclusively on the server, use. This is the #1 AI agent mistake. CRITICAL: TanStack Start is NOT Next.js. Do not generatecreateServerFn,getServerSidePropsdirectives,"use server", or any Next.js/Remix patterns. Useapp/layout.tsxfor server-only code. CRITICAL: Types are FULLY INFERRED. Never cast, never annotate inferred values.createServerFn
Use this entry skill to pick one primary workflow. Do not load every Start sub-skill. Add another only when the implementation crosses that boundary; for example, a protected mutation needs plus , while a public REST endpoint needs alone.
server-functionsauth-server-primitivesserver-routesTanStack Start 是一个基于 TanStack Router 和 Vite 的全栈 React 框架。它添加了 SSR、流式渲染、服务端函数(类型安全 RPC)、中间件、服务端路由和通用部署能力。
关键:TanStack Start 中的所有代码默认都是同构的——它同时运行在服务端和客户端环境中。Loader 同时运行在服务端和客户端。如果只想在服务端运行代码,请使用。这是 AI Agent 最容易犯的错误。 关键:TanStack Start 不是 Next.js。不要生成createServerFn、getServerSideProps指令、"use server"或任何 Next.js/Remix 模式。服务端专属代码请使用app/layout.tsx。 关键:类型是完全自动推断的。不要强制转换,不要为推断出的值添加类型标注。createServerFn
使用这个入口技能选择一个主要工作流。不要加载每个 Start 子技能。只有当实现跨越边界时才添加另一个技能;例如,受保护的变更操作需要 加上 ,而公共 REST 端点只需要 。
server-functionsauth-server-primitivesserver-routesSub-Skills
子技能
| Task | Sub-Skill |
|---|---|
| Type-safe RPCs, data fetching, mutations | start-core/server-functions/SKILL.md |
| Request/function middleware, context, auth | start-core/middleware/SKILL.md |
| Server-side auth: sessions, cookies, OAuth, CSRF | start-core/auth-server-primitives/SKILL.md |
| Isomorphic execution, environment boundaries | start-core/execution-model/SKILL.md |
| REST API endpoints alongside app routes | start-core/server-routes/SKILL.md |
| Hosting, SSR modes, prerendering, SEO | start-core/deployment/SKILL.md |
| 任务 | 子技能 |
|---|---|
| 类型安全 RPC、数据获取、变更操作 | start-core/server-functions/SKILL.md |
| 请求/函数中间件、上下文、认证 | start-core/middleware/SKILL.md |
| 服务端认证:会话、Cookie、OAuth、CSRF | start-core/auth-server-primitives/SKILL.md |
| 同构执行、环境边界 | start-core/execution-model/SKILL.md |
| 与应用路由并存的 REST API 端点 | start-core/server-routes/SKILL.md |
| 托管、SSR 模式、预渲染、SEO | start-core/deployment/SKILL.md |
Quick Decision Tree
快速决策树
text
Need to run code exclusively on the server (DB, secrets)?
→ start-core/server-functions
Need auth checks, logging, or shared logic across server functions?
→ start-core/middleware
Need to add login, sessions, OAuth, CSRF, password reset?
→ start-core/auth-server-primitives
Need to understand where code runs (server vs client)?
→ start-core/execution-model
Need a REST API endpoint (GET/POST/PUT/DELETE)?
→ start-core/server-routes
Need to deploy, configure SSR, or prerender?
→ start-core/deploymenttext
Need to run code exclusively on the server (DB, secrets)?
→ start-core/server-functions
Need auth checks, logging, or shared logic across server functions?
→ start-core/middleware
Need to add login, sessions, OAuth, CSRF, password reset?
→ start-core/auth-server-primitives
Need to understand where code runs (server vs client)?
→ start-core/execution-model
Need a REST API endpoint (GET/POST/PUT/DELETE)?
→ start-core/server-routes
Need to deploy, configure SSR, or prerender?
→ start-core/deploymentFull-Stack Delivery Workflow
全栈交付工作流
For application data loaded by a Start route:
- Put database, filesystem, secrets, and persistence code behind .
createServerFn - Call the server function directly from the route loader. Do not self-fetch a relative URL from an SSR loader.
/api/... - Validate every input and enforce auth in the server function or middleware. only protects route UX.
beforeLoad - After a mutation resolves, invalidate the router or the external query cache and await the refresh when the UI must be current before continuing.
- For schema changes, update storage, validation, handler serialization, loader, and UI. Assert the actual runtime payload; typechecking alone cannot detect an omitted serialized field.
Use a server route when the raw HTTP contract is the product: webhooks, third-party clients, feeds, file responses, or a public REST API. When the Start UI and a server route share data, call one server-side service from both instead of making the SSR loader fetch its own API route.
Before finishing, test the initial SSR request, client navigation, mutation followed by refresh, and a direct anonymous request to every protected endpoint.
对于由 Start 路由加载的应用数据:
- 将数据库、文件系统、密钥和持久化代码封装在 中。
createServerFn - 在路由 loader 中直接调用服务端函数。不要在 SSR loader 中自行请求相对的 URL。
/api/... - 在服务端函数或中间件中验证每个输入并强制认证。只保护路由层的 UI 体验。
beforeLoad - 变更操作完成后,使 router 或外部查询缓存失效,并在 UI 需要保持最新时等待刷新完成后再继续。
- 对于 schema 变更,更新存储、验证、处理器序列化、loader 和 UI。断言实际的运行时 payload;仅靠类型检查无法发现遗漏的序列化字段。
当原始 HTTP 契约本身就是产品时,使用服务端路由:webhook、第三方客户端、feed、文件响应或公共 REST API。当 Start UI 和服务端路由共享数据时,让两者都调用同一个服务端服务,而不是让 SSR loader 去请求自己的 API 路由。
在完成之前,测试初始 SSR 请求、客户端导航、变更后刷新,以及对每个受保护端点的直接匿名请求。
Project Setup
项目设置
1. Install Dependencies
1. 安装依赖
bash
npm i @tanstack/react-start @tanstack/react-router react react-dom
npm i -D vite @vitejs/plugin-react typescriptbash
npm i @tanstack/react-start @tanstack/react-router react react-dom
npm i -D vite @vitejs/plugin-react typescript2. Configure Vite
2. 配置 Vite
ts
// vite.config.ts
import { defineConfig } from 'vite'
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
import viteReact from '@vitejs/plugin-react'
export default defineConfig({
plugins: [
// MUST come before react()
tanstackStart(),
viteReact(),
],
})ts
// vite.config.ts
import { defineConfig } from 'vite'
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
import viteReact from '@vitejs/plugin-react'
export default defineConfig({
plugins: [
// MUST come before react()
tanstackStart(),
viteReact(),
],
})3. Create Router Factory
3. 创建 Router 工厂
tsx
// src/router.tsx
import { createRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen'
export function getRouter() {
const router = createRouter({
routeTree,
scrollRestoration: true,
})
return router
}tsx
// src/router.tsx
import { createRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen'
export function getRouter() {
const router = createRouter({
routeTree,
scrollRestoration: true,
})
return router
}4. Create Root Route with Document Shell
4. 创建带文档外壳的根路由
tsx
// src/routes/__root.tsx
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: RootComponent,
})
function RootComponent() {
return (
<html>
<head>
<HeadContent />
</head>
<body>
<Outlet />
<Scripts />
</body>
</html>
)
}tsx
// src/routes/__root.tsx
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: RootComponent,
})
function RootComponent() {
return (
<html>
<head>
<HeadContent />
</head>
<body>
<Outlet />
<Scripts />
</body>
</html>
)
}5. Create Index Route with Server Function
5. 创建带服务端函数的首页路由
tsx
// src/routes/index.tsx
import { createFileRoute } from '@tanstack/react-router'
import { createServerFn } from '@tanstack/react-start'
const getGreeting = createServerFn({ method: 'GET' }).handler(async () => {
return { message: 'Hello from the server!' }
})
export const Route = createFileRoute('/')({
loader: () => getGreeting(),
component: HomePage,
})
function HomePage() {
const data = Route.useLoaderData()
return <h1>{data.message}</h1>
}tsx
// src/routes/index.tsx
import { createFileRoute } from '@tanstack/react-router'
import { createServerFn } from '@tanstack/react-start'
const getGreeting = createServerFn({ method: 'GET' }).handler(async () => {
return { message: 'Hello from the server!' }
})
export const Route = createFileRoute('/')({
loader: () => getGreeting(),
component: HomePage,
})
function HomePage() {
const data = Route.useLoaderData()
return <h1>{data.message}</h1>
}Common Mistakes
常见错误
1. CRITICAL: React plugin before Start plugin in Vite config
1. 严重:Vite 配置中 React 插件放在 Start 插件之前
ts
// WRONG — route generation and server function compilation fail
plugins: [react(), tanstackStart()]
// CORRECT — Start plugin must come first
plugins: [tanstackStart(), react()]ts
// WRONG — route generation and server function compilation fail
plugins: [react(), tanstackStart()]
// CORRECT — Start plugin must come first
plugins: [tanstackStart(), react()]2. HIGH: Enabling verbatimModuleSyntax in tsconfig
2. 高:在 tsconfig 中启用 verbatimModuleSyntax
verbatimModuleSyntaxverbatimModuleSyntax3. HIGH: Missing Scripts component in root route
3. 高:根路由中缺少 Scripts 组件
The component must be rendered in the of the root route. Without it, client-side JavaScript does not load and hydration fails.
<Scripts /><body>tsx
// WRONG — no Scripts
function RootComponent() {
return (
<html>
<head>
<HeadContent />
</head>
<body>
<Outlet />
</body>
</html>
)
}
// CORRECT — Scripts in body
function RootComponent() {
return (
<html>
<head>
<HeadContent />
</head>
<body>
<Outlet />
<Scripts />
</body>
</html>
)
}<Scripts /><body>tsx
// WRONG — no Scripts
function RootComponent() {
return (
<html>
<head>
<HeadContent />
</head>
<body>
<Outlet />
</body>
</html>
)
}
// CORRECT — Scripts in body
function RootComponent() {
return (
<html>
<head>
<HeadContent />
</head>
<body>
<Outlet />
<Scripts />
</body>
</html>
)
}Version Note
版本说明
This skill targets v1.170.14.
@tanstack/start-client-core此技能面向 v1.170.14。
@tanstack/start-client-core