start-core

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

TanStack 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
createServerFn
. This is the #1 AI agent mistake. CRITICAL: TanStack Start is NOT Next.js. Do not generate
getServerSideProps
,
"use server"
directives,
app/layout.tsx
, or any Next.js/Remix patterns. Use
createServerFn
for server-only code. CRITICAL: Types are FULLY INFERRED. Never cast, never annotate inferred values.
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
server-functions
plus
auth-server-primitives
, while a public REST endpoint needs
server-routes
alone.
TanStack Start 是一个基于 TanStack Router 和 Vite 的全栈 React 框架。它添加了 SSR、流式渲染、服务端函数(类型安全 RPC)、中间件、服务端路由和通用部署能力。
关键:TanStack Start 中的所有代码默认都是同构的——它同时运行在服务端和客户端环境中。Loader 同时运行在服务端和客户端。如果只想在服务端运行代码,请使用
createServerFn
。这是 AI Agent 最容易犯的错误。 关键:TanStack Start 不是 Next.js。不要生成
getServerSideProps
、
"use server"
指令、
app/layout.tsx
或任何 Next.js/Remix 模式。服务端专属代码请使用
createServerFn
。 关键:类型是完全自动推断的。不要强制转换,不要为推断出的值添加类型标注。
使用这个入口技能选择一个主要工作流。不要加载每个 Start 子技能。只有当实现跨越边界时才添加另一个技能;例如,受保护的变更操作需要
server-functions
加上
auth-server-primitives
,而公共 REST 端点只需要
server-routes
。

Sub-Skills

子技能

TaskSub-Skill
Type-safe RPCs, data fetching, mutationsstart-core/server-functions/SKILL.md
Request/function middleware, context, authstart-core/middleware/SKILL.md
Server-side auth: sessions, cookies, OAuth, CSRFstart-core/auth-server-primitives/SKILL.md
Isomorphic execution, environment boundariesstart-core/execution-model/SKILL.md
REST API endpoints alongside app routesstart-core/server-routes/SKILL.md
Hosting, SSR modes, prerendering, SEOstart-core/deployment/SKILL.md
任务子技能
类型安全 RPC、数据获取、变更操作start-core/server-functions/SKILL.md
请求/函数中间件、上下文、认证start-core/middleware/SKILL.md
服务端认证:会话、Cookie、OAuth、CSRFstart-core/auth-server-primitives/SKILL.md
同构执行、环境边界start-core/execution-model/SKILL.md
与应用路由并存的 REST API 端点start-core/server-routes/SKILL.md
托管、SSR 模式、预渲染、SEOstart-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/deployment
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/deployment

Full-Stack Delivery Workflow

全栈交付工作流

For application data loaded by a Start route:
  1. Put database, filesystem, secrets, and persistence code behind
    createServerFn
    .
  2. Call the server function directly from the route loader. Do not self-fetch a relative
    /api/...
    URL from an SSR loader.
  3. Validate every input and enforce auth in the server function or middleware.
    beforeLoad
    only protects route UX.
  4. After a mutation resolves, invalidate the router or the external query cache and await the refresh when the UI must be current before continuing.
  5. 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 路由加载的应用数据:
  1. 将数据库、文件系统、密钥和持久化代码封装在
    createServerFn
    中。
  2. 在路由 loader 中直接调用服务端函数。不要在 SSR loader 中自行请求相对的
    /api/...
    URL。
  3. 在服务端函数或中间件中验证每个输入并强制认证。
    beforeLoad
    只保护路由层的 UI 体验。
  4. 变更操作完成后,使 router 或外部查询缓存失效,并在 UI 需要保持最新时等待刷新完成后再继续。
  5. 对于 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 typescript
bash
npm i @tanstack/react-start @tanstack/react-router react react-dom
npm i -D vite @vitejs/plugin-react typescript

2. 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

verbatimModuleSyntax
causes server bundles to leak into client bundles. Keep it disabled.
verbatimModuleSyntax
会导致服务端 bundle 泄漏到客户端 bundle 中。请保持禁用。

3. HIGH: Missing Scripts component in root route

3. 高:根路由中缺少 Scripts 组件

The
<Scripts />
component must be rendered in the
<body>
of the root route. Without it, client-side JavaScript does not load and hydration fails.
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>
中。缺少它时,客户端 JavaScript 不会加载,水合(hydration)会失败。
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
@tanstack/start-client-core
v1.170.14.
此技能面向
@tanstack/start-client-core
v1.170.14。