开发者指南
项目结构
Better SaaS 遵循基于 Next.js 15 App Router 的良好组织的项目结构,具有清晰的关注点分离和模块化架构。
概述
项目结构支持:
- 可扩展架构: 模块化组件和清晰分离
 - 类型安全: 整个代码库使用 TypeScript
 - 国际化: 使用 next-intl 的多语言支持
 - 现代工具: 最新的 Next.js 功能和最佳实践
 - 测试: 多级别的全面测试设置
 
根目录结构
better-saas/
├── .env.example                 # 环境变量模板
├── .gitignore                   # Git 忽略规则
├── biome.jsonc                  # 代码格式化和检查配置
├── components.json              # Shadcn/ui 组件配置
├── drizzle.config.ts           # 数据库 ORM 配置
├── jest.config.js              # Jest 测试配置
├── next.config.ts              # Next.js 配置
├── package.json                # 依赖和脚本
├── playwright.config.ts        # E2E 测试配置
├── postcss.config.js           # PostCSS 配置
├── README.md                   # 项目文档
├── source.config.ts            # Fumadocs 配置
├── tailwind.config.ts          # Tailwind CSS 配置
├── tsconfig.json               # TypeScript 配置
├── docs/                       # 文档文件
├── drizzle/                    # 数据库迁移
├── public/                     # 静态资源
├── scripts/                    # 构建和工具脚本
├── src/                        # 源代码
└── tests/                      # 测试文件源代码结构 (src/)
应用目录 (src/app/)
遵循 Next.js 15 App Router 约定:
src/app/
├── [locale]/                   # 国际化路由
│   ├── (home)/                # 首页组
│   │   ├── blocks/            # 块组件展示
│   │   ├── blog/              # 博客页面
│   │   ├── layout.tsx         # 首页布局
│   │   └── page.tsx           # 首页
│   ├── (protected)/           # 受保护路由组
│   │   ├── dashboard/         # 仪表板页面
│   │   └── settings/          # 设置页面
│   ├── docs/                  # 文档页面
│   ├── login/                 # 认证页面
│   ├── signup/
│   ├── layout.tsx             # 特定语言布局
│   └── page.tsx               # 语言根页面
├── api/                       # API 路由
│   ├── auth/                  # 认证端点
│   └── webhooks/              # Webhook 处理器
├── layout.tsx                 # 根布局
└── not-found.tsx              # 404 页面组件目录 (src/components/)
按功能和可重用性组织:
src/components/
├── ui/                        # 基础 UI 组件 (shadcn/ui)
│   ├── button.tsx
│   ├── card.tsx
│   ├── input.tsx
│   └── ...
├── blocks/                    # 页面块和部分
│   ├── hero/
│   ├── features/
│   ├── pricing/
│   ├── navbar/
│   └── footer/
├── auth/                      # 认证组件
│   ├── login-form.tsx
│   ├── signup-form.tsx
│   └── permission-provider.tsx
├── dashboard/                 # 仪表板组件
│   ├── dashboard-content.tsx
│   ├── dashboard-header.tsx
│   └── protected-layout-client.tsx
├── file-manager/              # 文件管理组件
│   ├── file-upload.tsx
│   ├── file-grid.tsx
│   └── file-table.tsx
├── payment/                   # 支付组件
│   ├── subscription-card.tsx
│   └── checkout-form.tsx
├── billing/                   # 账单组件
│   └── billing-page.tsx
├── settings/                  # 设置组件
│   ├── profile-content.tsx
│   └── security-content.tsx
├── providers/                 # 上下文提供者
│   ├── auth-provider.tsx
│   └── theme-provider.tsx
└── widget/                    # 可重用小部件
    ├── language-switcher.tsx
    ├── theme-toggle.tsx
    └── user-avatar-menu.tsx配置目录 (src/config/)
集中配置管理:
src/config/
├── app.config.ts              # 应用程序配置
├── features.config.ts         # 功能标志和设置
├── i18n.config.ts            # 国际化配置
├── navbar.config.ts          # 导航配置
├── payment.config.ts         # 支付计划和定价
├── theme.config.ts           # 主题配置
└── index.ts                  # 配置导出库目录 (src/lib/)
工具函数和服务:
src/lib/
├── auth/                      # 认证工具
│   ├── auth.ts               # 服务器端认证配置
│   ├── auth-client.ts        # 客户端认证
│   └── permissions.ts        # 权限系统
├── fumadocs/                 # 文档系统
│   ├── blog.ts
│   └── docs.ts
├── logger/                   # 日志工具
│   ├── logger.ts
│   └── logger-utils.ts
├── blocks-registry.ts        # 组件注册表
├── config-validation.ts     # 配置验证
├── file-service.ts          # 文件管理服务
├── r2-client.ts             # 云存储客户端
└── utils.ts                 # 通用工具服务器目录 (src/server/)
服务器端代码和数据库操作:
src/server/
├── actions/                   # 服务器操作
│   ├── auth-actions.ts
│   ├── file-actions.ts
│   ├── user-actions.ts
│   ├── payment/
│   │   ├── create-subscription.ts
│   │   ├── cancel-subscription.ts
│   │   └── get-billing-info.ts
│   └── error-messages.ts
├── db/                        # 数据库层
│   ├── index.ts              # 数据库连接
│   ├── schema.ts             # 数据库架构
│   ├── types.ts              # 数据库类型
│   ├── repositories/         # 数据访问层
│   │   ├── base-repository.ts
│   │   ├── file-repository.ts
│   │   └── payment-repository.ts
│   └── services/             # 业务逻辑层
│       └── index.ts
└── middleware/               # 服务器中间件国际化 (src/i18n/)
多语言支持:
src/i18n/
├── messages/                  # 翻译文件
│   ├── en.json               # 英文翻译
│   └── zh.json               # 中文翻译
├── navigation.ts             # 本地化导航
├── request.ts                # 请求配置
└── routing.ts                # 路由配置钩子目录 (src/hooks/)
自定义 React 钩子:
src/hooks/
├── use-config.ts             # 配置钩子
├── use-debounce.ts           # 防抖钩子
├── use-files.ts              # 文件管理钩子
├── use-login.ts              # 认证钩子
├── use-navbar.ts             # 导航钩子
├── use-profile.ts            # 个人资料钩子
└── use-toast-messages.ts     # 消息通知钩子类型目录 (src/types/)
TypeScript 类型定义:
src/types/
├── index.d.ts                # 全局类型定义
├── blocks.ts                 # 块组件类型
├── login.ts                  # 认证类型
├── navbar.ts                 # 导航类型
├── profile.ts                # 个人资料类型
└── stripe-extended.ts        # 扩展的 Stripe 类型内容目录 (src/content/)
静态内容和文档:
src/content/
├── blog/                     # 博客文章
│   ├── en/                   # 英文博客文章
│   └── zh/                   # 中文博客文章
└── docs/                     # 文档
    ├── en/                   # 英文文档
    └── zh/                   # 中文文档测试结构 (tests/)
全面的测试设置:
tests/
├── __mocks__/                # 模拟文件
├── e2e/                      # 端到端测试
│   ├── auth/
│   ├── dashboard/
│   ├── payment/
│   └── fixtures/
├── integration/              # 集成测试
│   ├── api/
│   ├── database/
│   └── services/
├── unit/                     # 单元测试
│   ├── components/
│   ├── hooks/
│   ├── lib/
│   └── server/
├── setup/                    # 测试设置文件
└── utils/                    # 测试工具文件命名约定
组件
- React 组件: PascalCase (例如: 
UserProfile.tsx) - 组件文件: kebab-case (例如: 
user-profile.tsx) - 钩子文件: kebab-case 带 
use-前缀 (例如:use-user-profile.ts) 
API 路由
- 路由文件: 目录结构中的 
route.ts - 中间件: 
middleware.ts - 服务器操作: kebab-case 带 
-actions后缀 
配置
- 配置文件: kebab-case 带 
.config.ts后缀 - 环境变量: 
.env.local,.env.example 
数据库
- 架构文件: 
schema.ts - 迁移文件: 时间戳前缀 (例如: 
0001_initial.sql) - 仓库文件: kebab-case 带 
-repository后缀 
导入/导出约定
桶导出
使用索引文件进行清晰的导入:
// src/components/ui/index.ts
export { Button } from './button'
export { Card } from './card'
export { Input } from './input'
// 使用
import { Button, Card, Input } from '@/components/ui'路径映射
在 tsconfig.json 中配置:
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "@/components/*": ["./src/components/*"],
      "@/lib/*": ["./src/lib/*"],
      "@/hooks/*": ["./src/hooks/*"],
      "@/types/*": ["./src/types/*"],
      "@/config/*": ["./src/config/*"]
    }
  }
}导入顺序
遵循以下导入顺序:
// 1. React 和 Next.js 导入
import React from 'react'
import { NextRequest, NextResponse } from 'next/server'
// 2. 第三方库
import { z } from 'zod'
import { clsx } from 'clsx'
// 3. 内部导入(绝对路径)
import { Button } from '@/components/ui/button'
import { useAuth } from '@/hooks/use-auth'
import { db } from '@/server/db'
// 4. 相对导入
import './styles.css'代码组织原则
单一职责
每个文件应该有一个单一、明确定义的目的:
// 好:专注于用户认证
// src/lib/auth/auth-client.ts
export const authClient = createAuthClient({...})
// 好:专注于文件操作
// src/lib/file-service.ts
export class FileService {
  async uploadFile() {...}
  async deleteFile() {...}
}依赖方向
依赖应该向内流动:
UI 组件 → 钩子 → 服务 → 数据库基于功能的组织
将相关功能组合在一起:
src/features/
├── auth/
│   ├── components/
│   ├── hooks/
│   ├── services/
│   └── types/
├── files/
│   ├── components/
│   ├── hooks/
│   ├── services/
│   └── types/
└── billing/
    ├── components/
    ├── hooks/
    ├── services/
    └── types/环境配置
环境文件
.env.local- 本地开发(不提交).env.example- 环境变量模板.env.production- 生产环境变量
环境变量结构
# 数据库
DATABASE_URL=postgresql://...
# 认证
BETTER_AUTH_SECRET=...
BETTER_AUTH_URL=...
# OAuth 提供商
GITHUB_CLIENT_ID=...
GITHUB_CLIENT_SECRET=...
# 支付
STRIPE_SECRET_KEY=...
STRIPE_PUBLISHABLE_KEY=...
# 文件存储
CLOUDFLARE_R2_ACCESS_KEY_ID=...
CLOUDFLARE_R2_SECRET_ACCESS_KEY=...
# 外部服务
RESEND_API_KEY=...构建和开发脚本
Package.json 脚本
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "biome check .",
    "lint:fix": "biome check . --apply",
    "type-check": "tsc --noEmit",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:integration": "jest --config=jest.integration.config.js",
    "test:e2e": "playwright test",
    "db:generate": "drizzle-kit generate",
    "db:migrate": "drizzle-kit migrate",
    "db:studio": "drizzle-kit studio"
  }
}性能考虑
代码分割
- 对大型组件使用动态导入
 - 实现基于路由的代码分割
 - 延迟加载非关键功能
 
包分析
# 分析包大小
npm run build -- --analyze
# 检查包组成
npx @next/bundle-analyzer树摇
- 使用 ES 模块以获得更好的树摇效果
 - 避免导入整个库
 - 谨慎使用桶导出
 
安全考虑
文件组织
- 将敏感配置保存在环境变量中
 - 清晰地分离客户端和服务器代码
 - 使用 TypeScript 确保类型安全
 
API 安全
- 使用 Zod 模式验证所有输入
 - 实现适当的认证检查
 - 对表单使用 CSRF 保护
 
最佳实践
组件设计
- 保持组件小而专注
 - 使用组合而不是继承
 - 实现适当的属性验证
 - 遵循无障碍指南
 
状态管理
- 对本地状态使用 React 钩子
 - 实现适当的错误边界
 - 使用服务器状态进行数据获取
 - 最小化全局状态
 
性能
- 实现适当的加载状态
 - 对昂贵的组件使用 React.memo
 - 优化图像和资源
 - 实现适当的缓存策略