项目结构
TanStack 模板中路由、服务、内容与 Cloudflare 资源的组织方式。
模板把 URL 结构、复用 UI、服务端集成与 Cloudflare 资源分开组织。TanStack
Router 根据 src/routes 生成路由树;业务代码不应直接修改生成文件。
顶层目录
路由层级
src/routes/__root.tsx 负责 HTML 外壳与全局 provider:SEO 默认值、主题初始化
脚本、ThemeProvider、Fumadocs RootProvider、toast、开发工具与 Router 脚本。
它刻意不放产品 header/footer,由下层布局决定页面外围结构。
src/routes/{-$locale}.tsx 增加一个可选语言段。英文不带前缀,中文位于
/zh 下。它的 beforeLoad 会校验语言、把 /en/* 重定向到无前缀规范 URL,
并在渲染前同步 i18next。
以下划线开头的 route ID 是无路径布局:用于组织 UI,但 URL 中不会出现
_marketing、_dashboard 或 _docs。
| 路由文件 | 职责 |
|---|---|
{-$locale}/_marketing.tsx | Banner、应用 header/footer、落地页、博客、法律页、联系页、AI 示例与支付成功页 |
{-$locale}/_dashboard.tsx | 受保护的侧栏外壳及 dashboard/account/settings 页面 |
{-$locale}/_docs.tsx | Fumadocs 目录树与文档布局 |
{-$locale}/auth.tsx | 登录、注册、确认和密码重置外壳 |
_marketing/blog/$slug.tsx 与 _marketing/legal/$slug.tsx 等动态文件通过
params.slug 取得末段路径;文档 catch-all 位于 _docs/docs/$.tsx。
src/router.tsx 创建 Router,并配置滚动恢复与 intent 预加载。它导入
src/routeTree.gen.ts,后者由 Router 插件根据路由文件自动生成。
不要编辑 src/routeTree.gen.ts。应在 src/routes 中新增、重命名或删除文件,
再让 TanStack Router 插件重新生成路由树。
API 路由与 Server Function
大多数 API 文件通过 server.handlers 暴露 HTTP 方法。Better Auth catch-all
保持得很薄:
export const Route = createFileRoute("/api/auth/$")({
server: {
handlers: {
GET: ({ request }) => auth.handler(request),
POST: ({ request }) => auth.handler(request),
},
},
})src/routes/api 下包含认证、用户/管理员、联系、支付、存储、聊天和 AI 媒体
接口。敏感接口必须再次检查 session;布局保护不能替代 API 授权。用户资料路由
体现了推荐模式:取得 session、用 Zod 校验变更,再用合适状态码返回
{ success, data } 或 { success: false, error }。
现有路由的认证、校验和响应结构并非完全统一。新增业务应以已认证、已校验的 用户路由为方向,并在产品化旧示例时逐步统一。
createServerFn 适合从组件或 Router hook 调用服务端逻辑,而无需单独设计 HTTP
接口。src/lib/auth-guard.ts 用它读取请求 session;_dashboard 布局在
beforeLoad 调用 requireAuth,管理员用户页则调用 requireAdmin。
其他目录
| 路径 | 内容 |
|---|---|
src/components | 功能 UI,以及 ui、home、layout、auth、ai、ai-elements、dashboard、motion 分类 |
src/config | 站点身份、路由、价格、footer、社交链接与侧栏配置 |
src/lib | 认证、守卫、D1/Drizzle、邮件、支付、存储、SEO、AI provider 与内容 loader |
src/i18n | i18next 初始化与语言感知路由辅助函数 |
src/hooks、src/types | 共用 hook 与 TypeScript 类型 |
messages | 英文与中文 UI 字典 |
content | Fumadocs 文档、博客与法律 MDX |
public | 随代码发布的静态资源;不是持久化上传存储 |
source.config.ts | Fumadocs collection schema |
drizzle.config.ts、drizzle/ | Drizzle Kit 配置与经审查的 SQLite migration |
wrangler.jsonc | Worker 名称、runtime 兼容性、路由、变量、D1 与 R2 binding |
#/* 与 @/* 都映射到 src/*;模板源码主要使用 #/*。
Workers 运行模型
D1 DB 与 R2 UPLOADS 是 Cloudflare binding,不是连接字符串。代码从
cloudflare:workers 导入 env,并在请求执行过程中读取 binding。数据库与认证
export 使用延迟 Proxy,Creem 与 Resend 使用延迟 factory/singleton,避免在模块
求值阶段捕获尚不可用的 Worker secret 或 binding。
新增 runtime client 时沿用这一模式:
- 把配置读取放在请求期间才会调用的函数中。
- 只在首次请求初始化后、且确实安全时缓存 client。
- 绝不在模块初始化时读取
DB或UPLOADS。 - 在每个服务端边界就近完成授权与输入校验。
