AI SaaS Template Docs
AI SaaS Template Docs
AI SaaS Template简介快速开始项目架构
配置管理项目结构数据库开发指南API 开发指南
认证系统文件管理支付和账单
自定义主题

项目架构

AI SaaS Template 采用现代化的技术架构设计,基于 Next.js 15 App Router、tRPC、Clerk Auth 和 Drizzle ORM 等前沿技术栈构建,确保应用的可扩展性、类型安全性和开发效率。

架构概览

技术栈架构

graph TB
    A[客户端] --> B[Next.js 15 App Router]
    B --> C[tRPC Client]
    C --> D[tRPC Server]
    D --> E[Clerk Auth 中间件]
    D --> F[Drizzle ORM]
    F --> G[PostgreSQL 数据库]
    
    B --> H[Tailwind CSS v4]
    B --> I[Radix UI 组件]
    
    D --> J[Stripe 支付]
    D --> K[AI 服务提供商]
    K --> L[OpenAI]
    K --> M[Anthropic]
    K --> N[Google AI]
    K --> O[XAI]
    
    G --> P[Upstash Redis]
    
    subgraph "部署环境"
        Q[Vercel]
        R[Neon/Supabase]
        S[Cloudflare R2]
    end

核心架构原则

  • 类型安全: 端到端的 TypeScript 类型安全,从数据库到前端
  • 服务器优先: 利用 Next.js 15 App Router 的服务器组件优势
  • API 优先: 基于 tRPC 的类型安全 API 开发
  • 模块化设计: 清晰的功能模块分离和组件化架构
  • 现代化工具: 使用最新的开发工具提升开发体验

前端架构

Next.js 15 App Router

src/app/
├── [locale]/                   # 国际化路由层
│   ├── (dashboard)/           # 仪表板路由组
│   ├── (front)/              # 前台页面路由组
│   ├── auth/                 # 认证页面
│   └── docs/                 # 文档页面
├── api/                      # API 路由
│   ├── trpc/                 # tRPC 端点
│   └── webhooks/             # Webhook 处理
└── globals.css               # 全局样式

组件架构

// 组件层次结构
src/components/
├── ui/                      # 基础 UI 组件 (shadcn/ui)
├── layout/                  # 布局组件
├── dashboard/               # 仪表板组件
├── auth/                    # 认证组件
├── payment/                 # 支付组件
├── ai/                      # AI 功能组件
├── providers/               # Context 提供者
└── common/                  # 通用组件

状态管理

// 使用 TanStack Query + tRPC 进行状态管理
const { data: user } = api.user.getProfile.useQuery()
const { mutate: updateProfile } = api.user.updateProfile.useMutation()

// 客户端状态使用 React 内置 state 和 context
const [theme, setTheme] = useTheme()

后端架构

tRPC API 层

// src/lib/trpc/routers/index.ts
export const appRouter = createTRPCRouter({
  auth: authRouter,        // 认证相关
  user: userRouter,        // 用户管理
  payment: paymentRouter,  // 支付功能
  ai: aiRouter,           // AI 功能
  admin: adminRouter,     // 管理后台
})

export type AppRouter = typeof appRouter

API 路由结构

src/lib/trpc/routers/
├── auth.ts              # 认证路由
├── user.ts              # 用户路由
├── payment.ts           # 支付路由
├── ai.ts                # AI 路由
├── admin.ts             # 管理路由
└── index.ts             # 根路由器

中间件和权限

// tRPC 中间件
export const protectedProcedure = publicProcedure.use(
  async ({ ctx, next }) => {
    if (!ctx.auth?.userId) {
      throw new TRPCError({ code: 'UNAUTHORIZED' })
    }
    
    const user = await getUserByClerkId(ctx.auth.userId)
    if (!user) {
      throw new TRPCError({ code: 'NOT_FOUND' })
    }
    
    return next({
      ctx: {
        ...ctx,
        user,
      },
    })
  }
)

数据层架构

Drizzle ORM 数据模型

// 核心数据表结构
export const users = pgTable('users', {
  id: text('id').primaryKey().$defaultFn(() => createId()),
  clerkId: text('clerk_id').notNull().unique(),
  email: text('email').notNull().unique(),
  name: text('name'),
  planType: text('plan_type', { enum: ['free', 'basic', 'pro'] }).default('free'),
  aiUsageCount: integer('ai_usage_count').default(0),
  createdAt: timestamp('created_at').defaultNow(),
})

export const conversations = pgTable('conversations', {
  id: text('id').primaryKey().$defaultFn(() => createId()),
  userId: text('user_id').references(() => users.id, { onDelete: 'cascade' }),
  title: text('title').notNull(),
  model: text('model').notNull(),
  provider: text('provider').notNull(),
  createdAt: timestamp('created_at').defaultNow(),
})

数据库关系

// 表关系定义
export const usersRelations = relations(users, ({ many }) => ({
  conversations: many(conversations),
  payments: many(payments),
  uploads: many(uploads),
}))

export const conversationsRelations = relations(conversations, ({ one, many }) => ({
  user: one(users, {
    fields: [conversations.userId],
    references: [users.id],
  }),
  messages: many(messages),
}))

认证架构

Clerk Auth 集成

// Clerk 配置
import { ClerkProvider } from '@clerk/nextjs'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <ClerkProvider
      publishableKey={env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY}
      appearance={{
        elements: {
          formButtonPrimary: 'bg-primary hover:bg-primary/90',
        },
      }}
    >
      {children}
    </ClerkProvider>
  )
}

认证流程

sequenceDiagram
    participant U as 用户
    participant C as Clerk Auth
    participant A as 应用
    participant D as 数据库
    
    U->>C: 登录请求
    C->>C: 验证凭据
    C->>A: 返回用户信息
    A->>D: 同步用户数据
    D->>A: 确认同步
    A->>U: 重定向到仪表板

权限控制

// 基于角色的访问控制
export function requireRole(role: 'admin' | 'user') {
  return protectedProcedure.use(async ({ ctx, next }) => {
    if (ctx.user.role !== role && ctx.user.role !== 'admin') {
      throw new TRPCError({ code: 'FORBIDDEN' })
    }
    return next({ ctx })
  })
}

// 使用示例
export const adminProcedure = requireRole('admin')

AI 服务架构

多提供商集成

// AI 服务抽象层
interface AIProvider {
  name: string
  models: string[]
  generateResponse(params: AIParams): Promise<AIResponse>
}

class OpenAIProvider implements AIProvider {
  name = 'openai'
  models = ['gpt-4', 'gpt-3.5-turbo']
  
  async generateResponse(params: AIParams): Promise<AIResponse> {
    // OpenAI 实现
  }
}

class AnthropicProvider implements AIProvider {
  name = 'anthropic'
  models = ['claude-3-sonnet', 'claude-3-haiku']
  
  async generateResponse(params: AIParams): Promise<AIResponse> {
    // Anthropic 实现
  }
}

AI 请求处理流程

graph LR
    A[用户输入] --> B[tRPC AI Router]
    B --> C[权限验证]
    C --> D[使用量检查]
    D --> E[AI 提供商选择]
    E --> F[API 调用]
    F --> G[响应处理]
    G --> H[数据库记录]
    H --> I[返回结果]

支付系统架构

Stripe 集成

// Stripe 配置
import Stripe from 'stripe'

export const stripe = new Stripe(env.STRIPE_SECRET_KEY, {
  apiVersion: '2023-10-16',
})

// 订阅创建
export async function createSubscription(userId: string, priceId: string) {
  const user = await getUserById(userId)
  
  const subscription = await stripe.subscriptions.create({
    customer: user.stripeCustomerId,
    items: [{ price: priceId }],
    payment_behavior: 'default_incomplete',
    expand: ['latest_invoice.payment_intent'],
  })
  
  return subscription
}

Webhook 处理

// Webhook 事件处理
export async function handleStripeWebhook(event: Stripe.Event) {
  switch (event.type) {
    case 'customer.subscription.created':
      await handleSubscriptionCreated(event.data.object)
      break
    case 'customer.subscription.updated':
      await handleSubscriptionUpdated(event.data.object)
      break
    case 'invoice.payment_succeeded':
      await handlePaymentSucceeded(event.data.object)
      break
  }
}

文件存储架构

多存储提供商支持

// 存储抽象层
interface StorageProvider {
  upload(file: File, key: string): Promise<string>
  delete(key: string): Promise<void>
  getUrl(key: string): string
}

class CloudflareR2Provider implements StorageProvider {
  async upload(file: File, key: string): Promise<string> {
    // Cloudflare R2 实现
  }
}

class AWSS3Provider implements StorageProvider {
  async upload(file: File, key: string): Promise<string> {
    // AWS S3 实现
  }
}

国际化架构

next-intl 集成

// i18n 配置
import { notFound } from 'next/navigation'
import { getRequestConfig } from 'next-intl/server'

export default getRequestConfig(async ({ locale }) => {
  if (!['en', 'zh'].includes(locale)) {
    notFound()
  }
  
  return {
    messages: (await import(`../messages/${locale}.json`)).default,
  }
})

路由本地化

app/
├── [locale]/
│   ├── page.tsx           # /{locale}
│   ├── dashboard/
│   │   └── page.tsx      # /{locale}/dashboard
│   └── auth/
│       └── sign-in/
│           └── page.tsx  # /{locale}/auth/sign-in

缓存架构

多层缓存策略

// Redis 缓存
import { Redis } from '@upstash/redis'

export const redis = new Redis({
  url: env.UPSTASH_REDIS_REST_URL,
  token: env.UPSTASH_REDIS_REST_TOKEN,
})

// 缓存装饰器
export function cached<T>(key: string, ttl: number = 3600) {
  return function (target: any, propertyName: string, descriptor: PropertyDescriptor) {
    const method = descriptor.value
    
    descriptor.value = async function (...args: any[]) {
      const cacheKey = `${key}:${JSON.stringify(args)}`
      
      let result = await redis.get(cacheKey)
      if (result) return result
      
      result = await method.apply(this, args)
      await redis.setex(cacheKey, ttl, JSON.stringify(result))
      
      return result
    }
  }
}

测试架构

测试策略

// 单元测试示例
describe('User API', () => {
  it('should create user', async () => {
    const caller = appRouter.createCaller({
      auth: { userId: 'test-user' },
      db,
    })
    
    const result = await caller.user.create({
      email: '[email protected]',
      name: 'Test User',
    })
    
    expect(result.email).toBe('[email protected]')
  })
})

// E2E 测试示例
test('should complete signup flow', async ({ page }) => {
  await page.goto('/auth/sign-up')
  await page.fill('[name="email"]', '[email protected]')
  await page.fill('[name="password"]', 'password123')
  await page.click('[type="submit"]')
  
  await expect(page).toHaveURL('/dashboard')
})

监控与日志

应用监控

// 错误监控
import * as Sentry from '@sentry/nextjs'

export function initMonitoring() {
  Sentry.init({
    dsn: env.SENTRY_DSN,
    integrations: [
      new Sentry.BrowserTracing(),
    ],
    tracesSampleRate: 1.0,
  })
}

// 性能监控
export function trackPerformance(operation: string, duration: number) {
  console.log(`${operation} took ${duration}ms`)
  
  // 发送到监控服务
  if (env.NODE_ENV === 'production') {
    // 发送性能数据
  }
}

部署架构

Vercel 部署

// vercel.json
{
  "functions": {
    "app/api/**/*": {
      "maxDuration": 30
    }
  },
  "regions": ["cle1"],
  "env": {
    "DATABASE_URL": "@database_url",
    "CLERK_SECRET_KEY": "@clerk_secret_key"
  }
}

CI/CD 流程

# .github/workflows/deploy.yml
name: Deploy to Vercel
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '20'
      
      - name: Install dependencies
        run: pnpm install
      
      - name: Run tests
        run: pnpm test
      
      - name: Run type check
        run: pnpm type-check
      
      - name: Deploy to Vercel
        run: vercel --prod --token=${{ secrets.VERCEL_TOKEN }}

安全架构

多层安全防护

// 输入验证
export const createUserSchema = z.object({
  email: z.string().email(),
  name: z.string().min(1).max(100),
})

// 权限验证
export function requireAuth() {
  return protectedProcedure.use(async ({ ctx, next }) => {
    if (!ctx.auth) {
      throw new TRPCError({ code: 'UNAUTHORIZED' })
    }
    return next({ ctx })
  })
}

// 限流
export function rateLimit(requests: number, window: string) {
  return middleware(async ({ ctx, next }) => {
    const key = `rate_limit:${ctx.auth?.userId}:${Date.now()}`
    const current = await redis.incr(key)
    
    if (current > requests) {
      throw new TRPCError({ code: 'TOO_MANY_REQUESTS' })
    }
    
    await redis.expire(key, parseTime(window))
    return next({ ctx })
  })
}

扩展性设计

微服务就绪

项目架构设计时考虑了未来的微服务拆分可能性:

  • 认证服务:基于 Clerk Auth 的独立认证
  • 支付服务:Stripe 集成的支付处理
  • AI 服务:多提供商的 AI 功能
  • 文件服务:云存储的文件管理
  • 通知服务:邮件和推送通知

性能优化

  • 服务器组件:利用 Next.js 15 的服务器组件减少客户端包大小
  • 代码分割:基于路由和功能的动态导入
  • 图片优化:Next.js Image 组件的自动优化
  • 数据库优化:索引优化和查询优化
  • 缓存策略:多层缓存提升响应速度

这个现代化的架构为构建可扩展、安全、高性能的 AI SaaS 应用提供了坚实的基础,结合了最新的技术栈和最佳实践。

On this page

架构概览技术栈架构核心架构原则前端架构Next.js 15 App Router组件架构状态管理后端架构tRPC API 层API 路由结构中间件和权限数据层架构Drizzle ORM 数据模型数据库关系认证架构Clerk Auth 集成认证流程权限控制AI 服务架构多提供商集成AI 请求处理流程支付系统架构Stripe 集成Webhook 处理文件存储架构多存储提供商支持国际化架构next-intl 集成路由本地化缓存架构多层缓存策略测试架构测试策略监控与日志应用监控部署架构Vercel 部署CI/CD 流程安全架构多层安全防护扩展性设计微服务就绪性能优化