SaaS 应用程序 — 项目 CLAUDE.md¶
这是 Next.js + Supabase + Stripe SaaS 应用程序的实际使用示例。 将其复制到项目根目录后,根据技术栈进行自定义。
项目概述¶
技术栈: Next.js 15 (App Router), TypeScript, Supabase (认证 + DB), Stripe (支付), Tailwind CSS, Playwright (E2E)
架构: 默认使用 Server Components。仅在需要交互时才使用 Client Components。API 路由用于 webhook,Server Action 用于 mutation。
核心规则¶
数据库¶
- 所有查询都使用启用了 RLS 的 Supabase client — 绝不绕过 RLS
- 迁移文件保存在
supabase/migrations/中 — 不直接修改数据库 - 使用包含显式列列表的
select(),而不是select('*') - 所有面向用户的查询必须包含
.limit(),以防止返回无限结果
认证¶
- 在 Server Components 中使用
@supabase/ssr的createServerClient() - 在 Client Components 中使用
@supabase/ssr的createBrowserClient() - 受保护路由使用
getUser()验证 — 不要单独依赖getSession()进行认证 middleware.ts中的 Middleware 会在每次请求时刷新认证令牌
支付¶
- Stripe webhook 处理器位于
app/api/webhooks/stripe/route.ts - 绝不信任客户端侧的价格数据 — 始终在服务器端从 Stripe 查询
- 订阅状态通过由 webhook 同步的
subscription_status列确认 - 免费计划用户:3 个项目,每日 100 次 API 调用
代码风格¶
- 禁止在代码或注释中使用 emoji
- 仅使用不可变模式 — 使用 spread 运算符,禁止直接修改
- Server Components:无
'use client'指令,无useState/useEffect - Client Components:在文件顶部编写
'use client',保持最小化 — 逻辑拆分到 hooks 中 - 所有输入验证优先使用 Zod schema(API 路由、表单、环境变量)
文件结构¶
src/
app/
(auth)/ # 인증 페이지 (로그인, 회원가입, 비밀번호 찾기)
(dashboard)/ # 보호된 대시보드 페이지
api/
webhooks/ # Stripe, Supabase webhooks
layout.tsx # Provider가 포함된 루트 레이아웃
components/
ui/ # Shadcn/ui 컴포넌트
forms/ # 유효성 검사가 포함된 폼 컴포넌트
dashboard/ # 대시보드 전용 컴포넌트
hooks/ # 커스텀 React hooks
lib/
supabase/ # Supabase client 팩토리
stripe/ # Stripe client 및 헬퍼
utils.ts # 범용 유틸리티
types/ # 공유 TypeScript 타입
supabase/
migrations/ # 데이터베이스 마이그레이션
seed.sql # 개발용 시드 데이터
主要模式¶
API 响应格式¶
type ApiResponse<T> =
| { success: true; data: T }
| { success: false; error: string; code?: string }
Server Action 模式¶
'use server'
import { z } from 'zod'
import { createServerClient } from '@/lib/supabase/server'
const schema = z.object({
name: z.string().min(1).max(100),
})
export async function createProject(formData: FormData) {
const parsed = schema.safeParse({ name: formData.get('name') })
if (!parsed.success) {
return { success: false, error: parsed.error.flatten() }
}
const supabase = await createServerClient()
const { data: { user } } = await supabase.auth.getUser()
if (!user) return { success: false, error: 'Unauthorized' }
const { data, error } = await supabase
.from('projects')
.insert({ name: parsed.data.name, user_id: user.id })
.select('id, name, created_at')
.single()
if (error) return { success: false, error: 'Failed to create project' }
return { success: true, data }
}
环境变量¶
# Supabase
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
SUPABASE_SERVICE_ROLE_KEY= # 서버 전용, 클라이언트에 절대 노출 금지
# Stripe
STRIPE_SECRET_KEY=
STRIPE_WEBHOOK_SECRET=
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=
# 앱
NEXT_PUBLIC_APP_URL=http://localhost:3000
测试策略¶
/tdd # 새 기능에 대한 단위 + 통합 테스트
/e2e # 인증 흐름, 결제, 대시보드에 대한 Playwright 테스트
/test-coverage # 80% 이상 커버리지 확인
核心 E2E 流程¶
- 注册 → 邮箱验证 → 创建第一个项目
- 登录 → 仪表盘 → CRUD 操作
- 套餐升级 → Stripe checkout → 订阅激活
- Webhook:取消订阅 → 降级到免费计划
ECC 工作流程¶
# 기능 계획 수립
/plan "Add team invitations with email notifications"
# TDD로 개발
/tdd
# 커밋 전
/code-review
/security-scan
# 릴리스 전
/e2e
/test-coverage
Git 工作流程¶
feat:新功能,fix:缺陷修复,refactor:代码更改- 从
main创建功能分支,必须提交 PR - CI 执行项:lint、类型检查、单元测试、E2E 测试
- 部署:提交 PR 时生成 Vercel 预览,合并到
main时进行生产部署
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 ev/ECC