Sistine Starter

项目结构

理解 Sistine Starter 的项目组织和代码架构

项目结构

Sistine Starter 采用模块化架构,基于 Next.js App Router,强调可扩展性和代码组织。

高层结构

sistine-starter/
├── app/                    # Next.js App Router (前端页面和 API)
├── lib/                    # 核心业务逻辑和工具函数
├── components/             # UI 组件库
├── features/              # 功能模块
├── content/               # 博客和文档内容
├── public/                # 静态资源
├── messages/              # 国际化翻译文件
├── constants/             # 常量定义
├── emails/                # 邮件模板
├── scripts/               # 实用脚本
├── drizzle/               # 数据库迁移
├── next.config.mjs        # Next.js 配置
├── tailwind.config.ts     # Tailwind CSS 配置
├── tsconfig.json          # TypeScript 配置
└── package.json           # 项目依赖

详细目录说明

1. app/ - Next.js App Router

app/
├── layout.tsx                               # 根布局
├── globals.css                              # 全局样式
├── favicon.ico
├── [locale]/                                # 国际化路由
│   ├── layout.tsx                          # 语言级布局 (主题, i18n, 分析)
│   ├── (auth)/                             # 认证相关路由 (分组)
│   │   ├── login/page.tsx
│   │   ├── signup/page.tsx
│   │   ├── forgot-password/page.tsx
│   │   └── reset-password/page.tsx
│   ├── (marketing)/                        # 营销页面 (分组)
│   │   ├── layout.tsx
│   │   ├── page.tsx                       # 首页
│   │   ├── blog/page.tsx                  # 博客列表
│   │   ├── blog/[slug]/page.tsx           # 博客文章
│   │   ├── pricing/page.tsx
│   │   ├── contact/page.tsx
│   │   ├── privacy/page.tsx
│   │   ├── terms/page.tsx
│   │   └── refund/page.tsx
│   ├── (protected)/                        # 受保护页面 (需要认证)
│   │   ├── layout.tsx
│   │   ├── dashboard/page.tsx
│   │   ├── profile/page.tsx
│   │   └── credits/page.tsx
│   ├── (admin)/                            # 管理员页面 (需要 admin 权限)
│   │   ├── layout.tsx
│   │   ├── admin/page.tsx
│   │   ├── admin/users/page.tsx
│   │   ├── admin/subscriptions/page.tsx
│   │   └── admin/credits/page.tsx
│   ├── demo/                               # AI 功能演示
│   │   ├── layout.tsx
│   │   ├── page.tsx
│   │   ├── chat/page.tsx
│   │   ├── image/page.tsx
│   │   └── video/page.tsx
│   ├── verify-email/page.tsx
│   └── check-email/page.tsx
├── api/                                     # API 路由
│   ├── auth/[...all]/route.ts             # Better Auth 集成
│   ├── chat/route.ts                       # AI 对话 (非流)
│   ├── chat/stream/route.ts                # 流式对话
│   ├── image/generate/route.ts             # 图像生成
│   ├── video/generate/route.ts             # 视频生成
│   ├── video/status/route.ts               # 视频状态查询
│   ├── user/profile/route.ts               # 用户信息
│   ├── user/credits/history/route.ts       # 积分历史
│   ├── user/admin-status/route.ts          # 检查管理员权限
│   ├── payments/creem/                     # 支付相关
│   │   ├── checkout/route.ts
│   │   ├── webhook/route.ts
│   │   └── redirect-placeholder/route.ts
│   ├── upload/
│   │   ├── simple/route.ts                # 简单上传
│   │   └── image/route.ts                 # 图片上传
│   ├── admin/users/[userId]/              # 管理员 API
│   │   ├── credits/route.ts                # 调整积分
│   │   └── subscription/route.ts           # 修改订阅
│   ├── newsletter/                         # 新闻通讯
│   │   ├── subscribe/route.ts
│   │   └── unsubscribe/route.ts
│   ├── cron/subscription-grants/route.ts  # 定时任务: 发放积分
│   └── llms-full.txt/route.ts             # LLM 完整文档端点
└── og/                                      # Open Graph 图像生成
    └── [slug]/route.tsx

路由分组说明:

  • (auth) - 不影响 URL,用于组织认证相关路由
  • (marketing) - 营销页面组
  • (protected) - 受保护页面(自动重定向到登录)
  • (admin) - 管理员页面

2. lib/ - 核心业务逻辑

lib/
├── auth.ts                    # Better Auth 配置
├── auth-client.ts            # 客户端认证 Hook
├── i18n.ts                    # 国际化配置
├── blog.ts                    # 博客加载逻辑
├── credits.ts                # 积分系统核心
│   ├── getUserCredits()       # 获取用户积分
│   ├── canUserAfford()        # 检查积分是否足够
│   ├── deductCredits()        # 扣除积分 (事务性)
│   └── refundCredits()        # 退还积分
├── email.ts                   # 邮件发送
├── utils.ts                   # 通用工具函数
├── r2-storage.ts             # S3 兼容存储
├── db/
│   ├── index.ts              # Drizzle ORM 初始化
│   └── schema.ts             # 完整数据库 Schema
├── auth/
│   └── admin.ts              # 管理员权限检查
├── billing/
│   └── subscription.ts       # 订阅和积分发放
├── payments/
│   └── creem.ts              # Creem 支付 API
└── volcano-engine/           # 火山引擎 AI 服务
    ├── index.ts
    ├── chat.ts               # 对话 API
    ├── image.ts              # 图像生成 API
    ├── video.ts              # 视频生成 API
    ├── config.ts
    └── types.ts

3. components/ - UI 组件库

components/
├── analytics/                # 分析工具脚本
│   ├── analytics.tsx
│   ├── google-analytics.tsx
│   ├── clarity-analytics.tsx
│   └── posthog-analytics.tsx
├── navbar.tsx               # 导航栏
├── footer.tsx               # 页脚
├── hero.tsx                 # 首页 Hero 部分
├── features.tsx             # 功能展示
├── cta.tsx                  # 行动呼吁
├── blog-card.tsx            # 博客卡片
├── blog-layout.tsx          # 博客文章布局
├── container.tsx            # 容器组件
├── heading.tsx              # 标题组件
├── button.tsx               # 按钮组件
├── badge.tsx                # 徽章组件
├── language-switcher.tsx    # 语言切换器
├── theme-switcher.tsx       # 主题切换器
├── grid-lines.tsx           # 网格背景
├── cobe.tsx                 # 全球地球仪 (可选)
└── [...其他 UI 组件]

4. features/ - 功能模块

features/
├── navigation/              # 导航功能
│   ├── navbar/
│   └── sidebar/
├── auth/                    # 认证功能
│   ├── login/
│   ├── signup/
│   └── password-reset/
├── admin/                   # 管理后台功能
│   ├── user-management/
│   ├── subscription-management/
│   └── analytics/
├── billing/                 # 计费功能
│   ├── pricing-table/
│   └── checkout/
└── ai/                      # AI 功能
    ├── chat/
    ├── image-generation/
    └── video-generation/

5. constants/ - 常量定义

constants/
├── website.ts               # 网站配置
│   ├── WEBSITE_NAME
│   ├── WEBSITE_DESCRIPTION
│   ├── SOCIAL_LINKS
│   └── ANALYTICS_CONFIG
├── billing.ts              # 定价和积分配置
│   ├── PRICING_PLANS
│   ├── CREDIT_COSTS
│   └── SUBSCRIPTIONS
├── tier.ts                 # 用户等级定义
└── routes.ts               # 路由定义

6. messages/ - 国际化翻译

messages/
├── en/
│   ├── common.json         # 通用翻译
│   ├── nav.json            # 导航翻译
│   ├── forms.json          # 表单翻译
│   ├── seo.json            # SEO 元数据
│   └── [...其他页面翻译]
├── zh/
│   ├── common.json
│   ├── nav.json
│   ├── forms.json
│   ├── seo.json
│   └── [...其他页面翻译]
└── i18n.config.ts          # i18n 配置

7. 其他目录

content/
├── blog/                   # 博客文章 (MDX)
│   ├── article-1/
│   │   ├── en.mdx
│   │   ├── zh.mdx
│   │   └── thumbnail.jpeg
│   └── [...更多文章]
└── docs/                   # 文档 (可选)

public/
├── og/                     # OG 图像
├── avatars/                # 头像
└── [其他静态资源]

emails/
├── verify-email.tsx        # 验证邮件模板
├── reset-password.tsx      # 重置密码模板
└── [...其他邮件模板]

scripts/
├── setup-admin.ts          # 创建管理员脚本
└── generate-blog.mjs       # 生成博客清单脚本

drizzle/
└── [日期]_xxxxx.sql       # 数据库迁移文件

关键配置文件

middleware.ts - 国际化和路由保护

import createMiddleware from 'next-intl/middleware';
import { locales, defaultLocale } from './i18n.config';

export default createMiddleware({
  locales,
  defaultLocale,
  localePrefix: 'as-needed'
});

export const config = {
  matcher: ['/', '/((?!api|_next|_vercel|.*\\..*).*)',]
};

i18n.config.ts - 国际化配置

export const locales = ['en', 'zh'] as const;
export const defaultLocale = 'en' as const;

export type Locale = (typeof locales)[number];

export const pathnames = {
  '/': '/',
  '/about': {
    en: '/about',
    zh: '/about',
  },
  '/blog': {
    en: '/blog',
    zh: '/blog',
  },
  // ...
};

routes.ts - 路由定义

export const routes = {
  home: '/',
  dashboard: '/dashboard',
  blog: '/blog',
  pricing: '/pricing',
  login: '/login',
  signup: '/signup',
  admin: '/admin',
  profile: '/profile',
};

代码组织最佳实践

1. 单一职责原则

每个文件应只做一件事:

// ✅ 好: 专注的 hook
export function useCredits(userId: string) {
  // 仅处理积分逻辑
}

// ❌ 避免: 混合多个职责
export function useCreditsAndAuth(userId: string) {
  // 混合了积分和认证逻辑
}

2. 导出约定

使用 barrel exports 简化导入:

// components/index.ts
export { Button } from './button';
export { Card, CardContent } from './card';
export { Navbar } from './navbar';

// 使用
import { Button, Card, Navbar } from '@/components';

3. 路由保护

使用 middleware 和布局保护:

// app/[locale]/(protected)/layout.tsx
import { requireAuth } from '@/lib/auth';

export default async function ProtectedLayout({ children }) {
  await requireAuth();  // 自动重定向未认证用户
  return <>{children}</>;
}

4. 服务端 vs 客户端

标记客户端组件:

'use client';  // 必须在文件顶部

import { useTheme } from 'next-themes';

export function ThemeSwitcher() {
  const { theme, setTheme } = useTheme();
  // ...
}

依赖关系图

app/
  ├─ 使用 → lib/ (业务逻辑)
  │         ├─ 使用 → lib/db/ (数据库)
  │         ├─ 使用 → lib/auth/ (认证)
  │         └─ 使用 → lib/payments/ (支付)

  ├─ 使用 → components/ (UI)
  │         └─ 使用 → constants/ (配置)

  ├─ 使用 → features/ (功能)
  │         └─ 使用 → components/

  └─ 使用 → messages/ (翻译)
            └─ 使用 → i18n/

lib/
  └─ 不依赖 app/ 或 components/ (解耦)

常见问题

1. 如何添加新功能模块?

1. 在 features/ 下创建新文件夹
   features/my-feature/
   ├── index.ts
   ├── component.tsx
   └── hook.ts

2. 创建 app/ 路由
   app/[locale]/(protected)/my-feature/page.tsx

3. 添加 lib/ 支持
   lib/my-feature.ts (业务逻辑)

2. 如何共享状态?

// 使用 Context API (轻量)
context/my-context.tsx

// 或使用 Zustand (复杂状态)
store/my-store.ts

3. 如何处理跨路由状态?

// 存储在 lib/ 并通过 prop drilling
// 或使用 URL 查询参数
// 或使用 Cookie (持久化)

下一步