一个基于 Next.js 16 的 Web 演示文稿编辑器。项目围绕“Slide XML 可视化编辑”展开:把幻灯片 XML 解析成可交互画布,在浏览器中完成编辑后再序列化回 XML,并结合 PostgreSQL 完成持久化、版本管理、评论协作与分享。
- XML round-trip 编辑链路:
XML -> 可编辑模型 -> HTML 画布 -> XML - 幻灯片编辑能力:拖拽、缩放、旋转、文本编辑、图形/表格插入、图层调整
- 文稿工作台:最近文稿、模板入口、个人中心
- 模板建稿:从系统模板快速生成新文稿
- 历史版本:版本列表、版本预览、回滚、差异查看
- 协作能力:分享链接、评论、评论汇总
- 导出能力:支持导出 PDF 与 PPTX
- AI 辅助:支持生成内容与局部编辑
- 鉴权与可观测性:Clerk 登录、Webhook 同步、Sentry 集成
- Framework: Next.js
16.1.6(App Router) - Runtime: React
19.2.3 - Language: TypeScript
- Styling: Tailwind CSS
v4 - State: Zustand + TanStack Query
- Database: PostgreSQL + Drizzle ORM
- Auth: Clerk
- XML: fast-xml-parser
- AI: Google Generative AI
- Export:
pptxgenjs+jspdf - Package Manager: Bun(优先)
parseSlideXml(xml)解析 XML,输出标准化的幻灯片模型features/slide-editor/store将模型映射到编辑态- 画布中完成文本、形状、表格和布局交互
serializeSlideDocument(model)将编辑结果序列化回 XML- 调用 API 保存至数据库,并写入版本记录
/:工作台首页,展示最近文稿与模板入口/decks/[deckId]:演示文稿编辑器/templates:模板中心/me:个人中心/share/[token]:通过分享链接进入文稿
GET /api/decks:文稿列表POST /api/decks:新建文稿GET /api/decks/:deckId:文稿详情PATCH /api/decks/:deckId:更新文稿标题GET /api/decks/:deckId/slides:幻灯片列表POST /api/decks/:deckId/slides:新增幻灯片PATCH /api/slides/:slideId:保存幻灯片GET /api/slides/:slideId/revisions:版本列表GET /api/slides/:slideId/revisions/:version:版本详情POST /api/slides/:slideId/rollback:版本回滚GET /api/decks/:deckId/comments:评论列表或汇总POST /api/decks/:deckId/comments:创建评论POST /api/decks/:deckId/share-links:创建分享链接GET /api/decks/:deckId/share-links:获取分享链接POST /api/ai/generate:AI 生成POST /api/ai/edit:AI 编辑POST /api/webhooks/clerk:同步 Clerk 用户事件
统一错误响应结构:
{
"ok": false,
"message": "错误描述",
"code": "ERROR_CODE"
}app/ 路由、Layout、页面、Route Handlers
components/ 公共组件
components/ui/ 原子级 UI 组件
features/ 按业务拆分的模块
hooks/ 通用 Hooks
lib/ 底层能力、数据库、鉴权、XML、AI
public/ 静态资源
scripts/ 本地脚本与冒烟脚本
types/ 全局共享类型
docs/ 设计文档、任务拆解与实现计划当前代码分层约定:
app/**只放路由与首屏数据组织features/**负责业务组件、hooks、server 逻辑components/ui/**保持无业务语义lib/**负责数据库、工具函数、解析/序列化等基础设施
bun install也可以使用:
npm install复制 .env.example 到 .env.local:
cp .env.example .env.local最小可用配置:
DATABASE_URL=postgres://<user>:<password>@<host>/<database>?sslmode=require
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxx
CLERK_SECRET_KEY=sk_test_xxx
CLERK_WEBHOOK_SECRET=whsec_xxx按需启用的可选配置:
GOOGLE_GENERATIVE_AI_API_KEY=your_gemini_api_key
NEXT_PUBLIC_APP_URL=http://localhost:3000
SHARE_LINK_SECRET=replace_with_a_random_secret
APP_BASE_URL=http://localhost:3000
NEXT_PUBLIC_SENTRY_DSN=https://<public_key>@o<org_id>.ingest.us.sentry.io/<project_id>
SENTRY_DSN=https://<public_key>@o<org_id>.ingest.us.sentry.io/<project_id>
SENTRY_ORG=your_org
SENTRY_PROJECT=your_project
SENTRY_AUTH_TOKEN=for_ci_only说明:
GOOGLE_GENERATIVE_AI_API_KEY用于 AI 生成与 AI 编辑接口NEXT_PUBLIC_APP_URL用于生成可分享链接APP_BASE_URL用于执行api:smokeSHARE_LINK_SECRET未配置时会回退到CLERK_SECRET_KEY
在 Clerk Dashboard 中:
- 启用
Google和GitHub登录方式 - 配置 webhook 指向
POST /api/webhooks/clerk - 本地开发时确保 Clerk 应用域名与本地回调配置一致
bun run db:migratebun run dev默认访问地址:
bun run dev # 启动开发环境
bun run lint # ESLint 检查
bun run build # 生产构建
bun run start # 启动生产服务
bun run db:migrate # 执行数据库迁移
bun run db:studio # 打开 Drizzle Studio
bun run api:smoke # API 冒烟测试(需 dev server 已启动)users:本地用户信息,与 Clerk 用户同步decks:演示文稿slides:演示文稿下的幻灯片slide_revisions:幻灯片历史版本deck_share_link:分享链接deck_member:协作成员与权限comment:评论与评论回复templates:模板数据
可以重点关注:
- 幻灯片版本:
unique(slide_id, version) - 幻灯片顺序:
unique(deck_id, position) - 分享能力:基于 token hash 与访问权限
- 评论能力:支持按 deck / slide / shape 维度组织
- 优先使用 Server Components,只有交互场景才添加
"use client" - 数据获取尽量放在服务端,避免客户端重复请求
- 尽量复用
features/、lib/和现有 UI 组件 - 变更保持最小范围,不顺手重构无关内容
如果你准备测试完整 PR 流程,这个 README 变更可以配合下面的检查点一起验证:
- 文档预览是否正常,Markdown 标题、代码块、列表是否渲染正确
- README 描述是否和当前仓库能力一致,尤其是分享、评论、AI、导出
- 按 README 执行本地启动流程时,是否能成功完成安装、迁移、启动
- Reviewer 是否能快速理解项目做什么、怎么跑、应该从哪里开始看代码
- PR 描述里可以把这次提交归类为
docs,验证 review、merge、通知等流程
- 暂未支持多人实时协同编辑
- 版本 diff 仍以当前实现为准,复杂场景仍需要继续补强
- AI 能力依赖外部模型服务,不配置密钥时相关接口不可用
- 本地调试分享、登录、Webhook 时需要正确配置外部服务
- 增加更完整的 XML round-trip 回归测试
- 增加编辑器 E2E 测试
- 持续完善版本 diff 展示
- 完善权限隔离与协作模型
- 优化大文稿下的性能表现