Inbox Zero贡献者指南:代码规范与开发流程说明
🎯 概述
欢迎加入Inbox Zero开源项目!本文档旨在为贡献者提供清晰的代码规范和开发流程指导,帮助您快速上手并高效参与项目开发。
Inbox Zero是一个基于Next.js的AI邮件助手应用,采用Monorepo架构,包含多个应用和共享包。项目使用TypeScript、Tailwind CSS、Prisma等技术栈,致力于提供智能邮件管理解决方案。
📋 开发环境要求
系统要求
- Node.js: >= 22.0.0
- pnpm: >= 8.6.12
- Docker Desktop (推荐但可选)
外部服务依赖
# 必需的环境变量服务
- Google OAuth (Gmail API访问)
- Microsoft OAuth (Outlook API访问)
- Redis (Upstash或本地Docker)
- PostgreSQL (数据库)
- LLM提供商 (OpenAI/Anthropic/Google Gemini等)
🛠️ 项目结构与架构
核心目录结构
inbox-zero/
├── apps/
│ ├── web/ # 主Web应用 (Next.js)
│ └── unsubscriber/ # 退订自动化服务
├── packages/ # 共享包
│ ├── loops/ # 营销邮件自动化
│ ├── resend/ # 事务性邮件发送
│ ├── tinybird/ # 实时分析
│ └── tsconfig/ # TypeScript配置
├── prisma/ # 数据库schema和迁移
├── store/ # Jotai状态管理
├── utils/ # 工具函数和核心逻辑
└── docker/ # Docker配置
📝 代码规范与质量标准
TypeScript规范
// 正确的类型定义示例
interface EmailRule {
id: string;
conditions: RuleCondition[];
actions: RuleAction[];
priority: number;
enabled: boolean;
}
// 使用严格的null检查
const processEmail = (email: Email | null): ProcessResult => {
if (!email) {
throw new Error('Email cannot be null');
}
// 处理逻辑
};
// 优先使用const枚举
const enum EmailCategory {
PRIMARY = 'primary',
SOCIAL = 'social',
PROMOTIONS = 'promotions',
UPDATES = 'updates'
}
React组件规范
// 组件文件结构示例
import { forwardRef } from 'react';
import { cva, type VariantProps } from 'class-variance-authority';
export interface ButtonProps
extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'color'>,
VariantProps<typeof buttonVariants> {
link?: { href: string; target?: React.HTMLAttributeAnchorTarget };
}
const buttonVariants = cva(
'inline-flex items-center justify-center transition-transform',
{
variants: {
size: { sm: 'px-2 py-1', md: 'px-2.5 py-1.5', lg: 'px-3 py-2' },
color: { primary: 'bg-gray-900', secondary: 'bg-gray-100' }
},
defaultVariants: { size: 'md', color: 'primary' }
}
);
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ size, color, className, ...props }, ref) => {
return (
<button
className={buttonVariants({ size, color, className })}
ref={ref}
{...props}
/>
);
}
);
Button.displayName = 'Button';
格式化与代码检查
项目使用Biome进行代码格式化和检查:
// biome.json 配置要点
{
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"correctness": {
"noUnusedImports": "warn",
"noUnusedVariables": "warn"
}
}
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2
}
}
常用命令:
# 检查代码规范
pnpm run lint
# 自动修复格式问题
pnpm run format-and-lint:fix
# 只检查不修复
pnpm run format-and-lint
🔄 开发工作流程
1. 环境设置
# 克隆项目
git clone https://gitcode.com/GitHub_Trending/in/inbox-zero
cd inbox-zero
# 安装依赖
pnpm install
# 复制环境变量模板
cp apps/web/.env.example apps/web/.env
# 启动Docker服务 (PostgreSQL + Redis)
docker-compose up -d
# 运行数据库迁移
pnpm prisma migrate dev
# 启动开发服务器
pnpm run dev
2. 功能开发流程
3. 提交信息规范
使用Conventional Commits规范:
# 功能新增
git commit -m "feat: 添加邮件分类功能"
# Bug修复
git commit -m "fix: 修复Gmail API连接问题"
# 文档更新
git commit -m "docs: 更新贡献者指南"
# 代码重构
git commit -m "refactor: 重构AI规则引擎"
# 测试相关
git commit -m "test: 添加邮件解析单元测试"
# 性能优化
git commit -m "perf: 优化数据库查询性能"
🧪 测试策略
测试金字塔结构
测试命令
# 运行所有测试
pnpm run test
# 运行AI相关测试
pnpm run test-ai
# 运行特定测试文件
pnpm test -- apps/web/__tests__/email-parser.test.ts
# 监听模式运行测试
pnpm test --watch
测试示例
// 单元测试示例
import { describe, it, expect } from 'vitest';
import { parseEmailSubject } from '@/utils/email';
describe('Email Parser', () => {
it('should parse standard email subject', () => {
const subject = 'Re: Meeting Tomorrow at 2PM';
const result = parseEmailSubject(subject);
expect(result).toEqual({
isReply: true,
originalSubject: 'Meeting Tomorrow at 2PM',
cleanSubject: 'Meeting Tomorrow at 2PM'
});
});
it('should handle empty subject', () => {
const result = parseEmailSubject('');
expect(result.cleanSubject).toBe('');
});
});
🚀 构建与部署
本地构建
# 构建生产版本
pnpm run build
# 启动生产服务器
pnpm start
# 使用Turborepo构建所有包
turbo build
Docker构建
# 生产环境Docker构建
docker build \
--build-arg NEXT_PUBLIC_BASE_URL="https://your-domain.com" \
-t inbox-zero \
-f docker/Dockerfile.prod .
# 运行Docker容器
docker run -p 3000:3000 \
-e DATABASE_URL="postgresql://user:pass@host:5432/db" \
-e AUTH_SECRET="your-secret" \
inbox-zero
🔧 常用开发工具
VS Code推荐配置
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "biomejs.biome",
"typescript.preferences.includePackageJsonAutoImports": "on",
"emmet.includeLanguages": {
"typescript": "typescriptreact"
}
}
调试配置
// .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Next.js: debug server-side",
"type": "node-terminal",
"request": "launch",
"command": "pnpm run dev"
}
]
}
🤝 贡献指南
如何开始贡献
- 查看现有Issue: 在GitHub Issues中寻找适合的任务
- 加入Discord: 参与社区讨论和任务分配
- 从小任务开始: 从文档改进或简单Bug修复开始
- 遵循代码规范: 确保代码符合项目标准
Pull Request流程
- 创建功能分支:
git checkout -b feature/your-feature - 开发并测试: 确保所有测试通过
- 提交代码: 使用规范的提交信息
- 创建PR: 提供清晰的描述和测试结果
- 响应反馈: 根据审查意见进行修改
代码审查标准
| 审查项目 | 标准要求 |
|---|---|
| 代码质量 | 符合Biome规范,无lint错误 |
| 测试覆盖 | 新增功能包含相应测试 |
| 性能考虑 | 无明显的性能问题 |
| 文档更新 | 相关文档同步更新 |
| 向后兼容 | 不影响现有功能 |
🐛 常见问题解决
环境配置问题
# 如果pnpm安装失败
corepack enable pnpm
pnpm install --frozen-lockfile
# 数据库连接问题
检查DATABASE_URL环境变量格式:
postgresql://username:password@localhost:5432/database_name
# Redis连接问题
确保UPSTASH_REDIS_URL和UPSTASH_REDIS_TOKEN正确设置
开发常见错误
// 避免常见的TypeScript错误
// 错误:使用any类型
const processData = (data: any) => { ... }
// 正确:使用具体类型或unknown
const processData = (data: unknown) => {
if (typeof data === 'string') { ... }
}
📊 性能优化指南
数据库优化
// 避免N+1查询问题
// 错误方式
const users = await prisma.user.findMany();
for (const user of users) {
const emails = await prisma.email.findMany({ where: { userId: user.id } });
}
// 正确方式:使用include或单独查询
const usersWithEmails = await prisma.user.findMany({
include: { emails: true }
});
React性能优化
// 使用React.memo避免不必要的重渲染
const ExpensiveComponent = React.memo(({ data }) => {
return <div>{/* 复杂渲染逻辑 */}</div>;
});
// 使用useCallback和useMemo
const memoizedCallback = useCallback(() => {
doSomething(a, b);
}, [a, b]);
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
🎉 总结
通过遵循本文档的规范和流程,您将能够:
- ✅ 快速设置开发环境
- ✅ 编写符合标准的代码
- ✅ 高效参与项目开发
- ✅ 通过代码审查流程
- ✅ 为项目做出有价值的贡献
感谢您对Inbox Zero项目的贡献!如有任何问题,请随时在Discord社区或GitHub Issues中提问。
Happy Coding! 🚀
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



