Notion 很好用,但总有些地方想改——AI 功能需要付费订阅、AI 对话不能基于自己的文档知识库、移动端体验不够原生、数据不在自己手里。于是我造了一个定制化的个人版 Notion,把 AI 能力直接塞进编辑器和知识库里,而且完全开源免费。
这篇文章会聊聊这个项目的技术选型、架构设计、如何借助 AI Agent 加速开发,以及你能从中学到什么。
技术栈一览
| 技术 | 版本 | 说明 |
|---|---|---|
| Next.js | 16 | Turbopack 默认构建,App Router |
| React | 19 | 最新稳定版 |
| Expo | 54 | React Native 0.81 |
| TypeScript | 5.9 | 严格模式 |
| Hono | 4.x | 轻量 AI 网关 |
| Zustand | 5 | 跨端状态管理 |
| BlockNote | 0.41 | Notion 风格编辑器 |
| Qdrant | — | 向量数据库 |
| LangChain | — | RAG 流程编排 |
技术栈选型的核心原则是选最新稳定版——Next.js 16、React 19、Expo 54 都是当前各框架的最新正式版,不是 canary 或 beta。同时通过完整的 CI/CD(Build / Lint / TypeCheck / Unit Test / E2E)和 Sentry 监控来保障稳定性。
架构设计
Monorepo 跨端共享
项目采用 pnpm workspace 管理,核心思路是把重复代码抽到共享包,Web 和 Mobile 只写各自独有的 UI 层:
My-Notion/
├── apps/
│ ├── web/ # Next.js 16 Web 应用
│ └── mobile/ # Expo 54 移动应用
├── packages/
│ ├── ai/ # AI 核心 — RAG、Chat、Embeddings、Tools
│ ├── business/ # 业务共享 — Zustand Stores、i18n、Types
│ └── convex/ # 数据层 — Schema、Documents、Chat 逻辑
├── services/
│ └── ai/ # Hono AI 网关
三个共享包的分工:
@notion/ai:RAG 检索、流式 Chat、Embeddings、工具调用。Web 端直接调用,Mobile 端通过 AI 网关调用,但核心逻辑只有一份@notion/business:AI 模型选择、知识库开关、深度思考等 Zustand Store,Web 和 Mobile 行为完全一致@notion/convex:Convex 数据库的 Schema 定义和业务逻辑(文档 CRUD、AI 对话管理),两端共享同一套"超集"实现
这意味着改一个 AI 逻辑或数据库查询,Web 和 Mobile 同时生效,零重复代码。
AI 架构:RAG + 流式 + 工具调用
AI 不是独立对话框,而是深度融入知识管理流程:
用户提问
→ Web/Mobile UI
→ Hono AI Service (API Key 安全代理)
→ @notion/ai
├─ Qdrant 向量检索 (基于用户文档知识库)
├─ LLM API (通义千问)
└─ 工具调用 (Web 搜索等)
← 流式响应 (NDJSON/SSE)
← 实时渲染
几个值得说的设计决策:
- RAG 增量更新:用 SHA-256 内容哈希判断文档是否变化,配合向量存储缓存,避免每次启动都重新嵌入所有文档
- 双协议流式:Web 端用 NDJSON,Mobile 端用 SSE,但底层
@notion/ai的streamChat只写一次 - API Key 代理:Mobile 端不存储任何 LLM API Key,所有 AI 请求通过 Hono 网关转发,密钥只在服务端
- 深度思考可视化:AI 的推理过程(类似 o1 的思维链)可以实时展示给用户,让回答不只是结果,还有过程
- 工具调用系统:AI 可以主动调用 Web 搜索等外部工具,获取实时信息补充回答
安全代理设计
Mobile 端面临一个特殊问题:React Native 客户端无法安全存储 API Key。解决方案是两层代理:
# AI 调用
Mobile → Hono AI Service → LLM API
# 文件上传
Mobile → Web API (/api/upload-image) → EdgeStore
客户端永远不接触密钥,所有敏感操作都由服务端代理完成。Hono 网关只用了约 100 行代码就实现了完整的代理 + 错误监控,非常轻量。
国际化架构
Web 和 Mobile 使用不同的 i18n 方案,但翻译内容统一管理在 @notion/business/i18n/ 中:
- Web 端:
next-intl,服务端渲染,URL 路径携带 locale(/en/documents、/zh-CN/documents) - Mobile 端:
i18next+react-i18next,客户端切换
翻译文件遵循 PascalCase 命名空间 + camelCase 字段的规范,两端共享同一份翻译源。
工程化体系
代码推送 → GitHub Actions
├─ Build (Web + AI Service)
├─ Lint + TypeCheck + Unit Tests (Vitest, 67+ 用例)
└─ E2E Tests (Playwright)
→ Vercel 自动部署
→ Sentry 线上监控
几个实际踩过的坑:
next lint在 Next.js 16 中被移除,需要自己写 ESLint Flat Config(eslint.config.mjs)- BlockNote 不兼容 React 19 StrictMode,
next.config.js中必须reactStrictMode: false - 重型库必须动态导入:
emoji-picker-react(~800KB)和BlockNote(~1.4MB)用next/dynamic拆分,首屏不加载 @next/bundle-analyzer不兼容 Turbopack,分析 Bundle 时需要--webpack标志- Fork PR 无法访问 GitHub Secrets,需要
NEXT_IGNORE_ENV_VALIDATION=1让 Build 在缺少环境变量时也能通过
如何借助 AI Agent 加速开发
这个项目从零到当前规模,大量开发工作是借助 AI Agent 完成的。这里分享一些实际经验——不是"AI 能帮你写代码"这种空话,而是具体怎么让 AI Agent 真正成为高效的开发伙伴。
选择合适的 Agent 工具
目前主流的编码 Agent 有几类:
| 工具 | 特点 | 适合场景 |
|---|---|---|
| Cursor | IDE 深度集成,Tab 补全强 | 日常编码、快速修改 |
| Trae | 多轮对话 + 上下文记忆,适合大任务 | 架构设计、跨文件重构 |
| Claude Code | 命令行 Agent,擅长代码审查 | 代码审查、Bug 排查 |
| GitHub Copilot | 轻量补全 | 日常编码辅助 |
这个项目主要使用 Trae + Cursor 组合:Trae 负责架构设计和跨文件的大任务(比如把 1400 行的 documents.ts 拆分到共享包),Cursor 负责日常编码和快速修改。
让 Agent 理解你的项目
AI Agent 最大的问题不是"不会写代码",而是"不了解你的项目"。解决方法:
1. 写好项目规则文件
在项目根目录创建 CLAUDE.md 或 .trae/rules/project_rules.md,写清楚:
## 技术栈
- Next.js 16 + React 19 + TypeScript 5.9
- Expo 54 + React Native 0.81
- Convex 实时数据库 + EdgeStore 文件存储
## 硬约束
- Mobile 端文件上传必须通过 Web 端 API 代理转发
- Mobile AI 调用必须通过 Hono AI 服务转发
- 统一使用 Zustand 进行状态管理
- 重型第三方库必须使用 Next.js dynamic 导入
## 代码风格
- 不使用 class 组件,全部函数式 + Hooks
- 状态管理优先使用共享包中的 Zustand Store
- i18n 命名:PascalCase 命名空间,camelCase 字段
这样 Agent 每次对话都会读取这些规则,不会犯"在 Mobile 端直接调用 EdgeStore 密钥"这种错误。
2. 分阶段推进,不要一口吃成胖子
不要跟 Agent 说"帮我做一个完整的 Notion",而是拆成具体的小任务:
❌ "帮我实现 AI 对话功能"
✅ "在 apps/web/src/app/api/chat/route.ts 中,基于 @notion/ai 的 streamChat
实现一个 POST 接口,接收 messages 数组,返回 NDJSON 流式响应"
这个项目实际的任务拆分方式:
P0 — 核心功能
P0-1: Web 端文档编辑 + Convex 数据层
P0-2: 用户认证 (Clerk)
P0-3: 文件上传 (EdgeStore)
P1 — Mobile 对齐
P1-1: Mobile 端文档列表 + 编辑
P1-2: Mobile 端 AI 对话
P1-3: Mobile 端图片上传代理
P2 — 架构收敛
P2-1: Web AI Chat 页面拆分 (805行 → 157行)
P2-2: RAG 增量更新优化
P2-3: i18n 规范统一
P2-4: Convex 逻辑收敛至共享包
P2-5: AI Store 公共化
每个任务都有明确的输入输出,Agent 执行起来效率很高。
3. 善用 Agent 的代码审查能力
写完代码后,让 Agent 做一轮 review。这个项目中,Agent 曾发现了一个我遗漏的 Bug:
// Agent 发现 clearVectorStoreCache 只清理了 vectorStoreCache
// 遗漏了 documentSyncCache
export function clearVectorStoreCache(userId?: string) {
if (userId) {
vectorStoreCache.delete(userId);
// ❌ 缺少 documentSyncCache.delete(userId)
} else {
vectorStoreCache.clear();
// ❌ 缺少 documentSyncCache.clear()
}
}
这种"自己写的代码自己 review 不出来"的问题,Agent 反而能发现。
4. CI/CD 是 Agent 的安全网
Agent 写的代码不一定 100% 正确,但 CI/CD 可以帮你兜底。这个项目的工作流是:
Agent 写代码 → 我快速 review → push 到分支
→ GitHub Actions 自动跑 Build + Lint + TypeCheck + Test
→ 全部通过才合并到 main
Agent 不需要完美,CI 会告诉你哪里出了问题。然后你把错误信息贴给 Agent,它通常能快速修复。
Agent 做得好和做得不好的事
做得好的:
- 跨文件重构(把 1400 行文件拆成 20 个小模块)
- 写测试用例(Vitest 67 个用例大部分是 Agent 写的)
- 搭建 CI/CD workflow(GitHub Actions YAML 配置)
- 修复 lint 错误(17 个 ESLint 错误一轮修完)
- Bundle 优化(动态导入、tree-shaking 建议)
做得不好的:
- 复杂的 UI 交互细节(动画、手势、布局微调还是需要人工)
- 跨端兼容性判断(比如 Mobile 端 WebView 的特殊行为)
- 业务决策("这个功能要不要做"只能人决定)
如何拉取和运行
环境准备
- Node.js 22.0+(推荐 22 LTS)
- pnpm 10+(
npm install -g pnpm) - Git
第三方服务账号(免费额度足够开发使用):
| 服务 | 用途 | 注册地址 |
|---|---|---|
| Convex | 实时数据库 | convex.dev |
| Clerk | 用户认证 | clerk.com |
| EdgeStore | 文件存储 | edgestore.dev |
| Qdrant | 向量数据库 | cloud.qdrant.io |
| 通义千问 | LLM API | dashscope.console.aliyun.com |
克隆项目
git clone https://github.com/HaveNiceDa/My-Notion.git
cd My-Notion
pnpm i
配置环境变量
在 apps/web/ 下创建 .env.local:
# Convex
CONVEX_DEPLOYMENT=dev:your-deployment-id
NEXT_PUBLIC_CONVEX_URL=https://your-deployment.convex.cloud
NEXT_PUBLIC_CONVEX_SITE_URL=https://your-deployment.convex.site
# Clerk
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...
CLERK_JWT_ISSUER_DOMAIN=https://your-instance.clerk.accounts.dev
# EdgeStore
EDGE_STORE_ACCESS_KEY=your-access-key
EDGE_STORE_SECRET_KEY=your-secret-key
# Qdrant
NEXT_PUBLIC_QDRANT_URL=https://your-cluster.qdrant.io
NEXT_PUBLIC_QDRANT_API_KEY=your-api-key
# LLM
LLM_API_KEY=your-dashscope-api-key
启动开发
# Web 应用(同时启动 Next.js dev + Convex dev)
cd apps/web
pnpm start
# Mobile 应用
cd apps/mobile
pnpm start
# AI 网关服务
cd services/ai
pnpm dev
运行测试
# 单元测试(67+ 用例)
pnpm test
# E2E 测试(需先启动 Web dev server)
pnpm exec playwright test
你能从中学到什么
1. Monorepo 跨端架构实践
不是简单的"共享类型定义",而是真正把业务逻辑、状态管理、AI 能力抽到共享包。你会看到:
packages/convex如何让 Web 和 Mobile 共享同一套数据库逻辑,同时保持各自的入口文件packages/business的 Zustand Store 如何在 Web(Next.js)和 Mobile(Expo)中无缝使用packages/ai的streamChat如何同时支持 NDJSON(Web)和 SSE(Mobile)两种流式协议
2. RAG 从 0 到 1 的完整实现
从文档分块、向量嵌入、相似度检索到流式回答,完整的 RAG 链路:
- 文档变更时自动触发增量嵌入(SHA-256 哈希去重)
- Qdrant 向量数据库的用户隔离设计
- 流式响应的前端渲染(React 19 下的
ReadableStream处理) - 深度思考过程可视化(思维链实时展示)
3. Next.js 16 的实战踩坑
Next.js 16 变化很大,文档还没完全跟上,这个项目踩过的坑包括:
- Turbopack 默认启用后,
@next/bundle-analyzer需要切回 Webpack - ESLint Flat Config 替代了
.eslintrc,next lint命令被移除 useSyncExternalStore替代useState + useEffect的 mounted 模式- Convex 的
useQuery条件调用需要"skip"参数 - Sentry
withSentryConfig包装next.config.js的正确写法
4. Mobile 端的安全代理模式
React Native 客户端无法安全存储密钥,这个项目展示了完整的代理方案:
- Hono 搭建轻量 AI 网关(~100 行代码),代理 LLM 调用
- Web API 路由代理文件上传,添加 CORS 头支持 Mobile 跨域
- EdgeStore 客户端初始化只在服务端执行
5. 工程化闭环搭建
从零搭建 CI/CD 的完整过程:
- GitHub Actions 三条 Workflow(Build / Lint+TypeCheck+UnitTest / E2E)
NEXT_IGNORE_ENV_VALIDATION=1让 Fork PR 也能跑通 Build- Sentry 接入 + Source Map 上传 + 性能监控
- Bundle 优化:动态导入重型组件、
optimizePackageImports、tree-shaking
6. 用 AI Agent 驱动开发的方法论
不只是"让 AI 写代码",而是建立一套人机协作的工作流:
- 项目规则文件 → 让 Agent 理解约束
- 分阶段任务拆分 → 让 Agent 有明确目标
- CI/CD 兜底 → 让 Agent 的错误可以被自动捕获
- Agent 代码审查 → 发现人类容易遗漏的 Bug
后续规划
项目还在持续迭代,接下来的重点方向:
- AI 原生编辑器:在 BlockNote 中选中文字直接调用 AI(翻译、润色、提问),让 AI 成为编辑器的一等公民
- RAG 增强:分层检索、混合检索、多格式文档支持、检索结果溯源
- Mobile 上架:iOS App Store / Android Google Play
- CLI & Agent:
notion create、notion search、notion ask,让 AI Agent 也能操作你的知识库
如果你对全栈开发、AI 应用、或者想用 AI Agent 加速自己的项目,欢迎 Star ⭐ 和参与贡献!
如果有问题或建议,欢迎在 GitHub Issues 中讨论。