Skip to content

ADR-008 · Handbook 站点框架选型 · VitePress on /handbook/

字段
状态accepted · 2026-06-01
日期2026-06-01
决策者CTO + 项目主理
承接ADR-005 (CF Pages hybrid 部署) · ADR-006 (公开仓库脱敏 4 层)
相关writing/handbook-build-plan.md · handbook-src/ (本 ADR 引入) · www/_redirects · www/sitemap.xml

1. Context

1.1 · 起源 · 平铺 .md 与 trajectory.ai 体验差距

ADR-005 hybrid 落地后, www/ 在 CF Pages 上 serve 一组平铺的公开 .md (installation.md / user-manual.md / deployment.md / api-contracts.md / troubleshooting.md / dev-quickstart.md / deployment-hybrid.md / site-update-workflow.md) + 一张 docs.html 静态目录页. 用户点开 .md 时, CF 直接 serve 裸 markdown — 浏览器渲染依赖 CF 默认 handling, 没有 sidebar 导航、没有 search、没有代码语法高亮、没有 dark mode、没有锚点 TOC.

用户参考 https://docs.trajectory.ai 提出诉求: 把公开方法论文档升级为可浏览手册站, 域名内入口可以是 https://www.apex.fan/docs/ 或类似路径.

1.2 · 路径选择的隐藏约束

直觉上选 /docs/, 但 www/_redirects 已有:

/docs/*                     /404.html         404

这条是 ADR-005 §3 隐含的 invariant: docs/internal/ 是 vault 本地保留的私密文档目录 (gitignored, ADR-006 P1.5), /docs/* → 404 是反搜索引擎索引的拦截规则, 防止任何 /docs/whatever 路径被 CF Pages 渲染或被 SEO 抓取.

直接撤掉这条 → 让 /docs/ 能用 — 会让 ADR-005/ADR-006 的"docs/ 路径永远 404"承诺失效. 即便 docs/internal/ gitignored 不在 build 输出里, 失去拦截规则后未来任何手滑把 docs/foo.md 加进 build 都会自动公网可见. 不能撤.

1.3 · 用户决策

询问"框架 × 路径 × 视觉 × 部署"4 维选型:

  • 框架: A VitePress / B Mintlify / C 手写 HTML / D Docusaurus → A VitePress
  • 路径: 用户主动放弃 /docs/, 接受重命名 → 选 /handbook/ (调性 ≫ /guide/ /playbook/ /learn/, 与"判断力工程化"=方法论手册一致)
  • 视觉: 继承 www/index.html DNA (深色 nav + 红 #b8331f + Source Han Serif SC + JetBrains Mono)
  • 部署: 同一个 CF Pages project, 不开 docs.apex.fan 子域

2. Decision

采用 VitePress 静态生成器, 部署在现有 CF Pages project 的 /handbook/ 路径下, 主题继承 www/index.html 设计 DNA, 源码放新顶层 handbook-src/ 目录.

┌─ 源代码 (git tracked) ─────────────────────────────────────┐
│  handbook-src/                                            │
│    ├── .vitepress/config.ts        ← nav / sidebar / search│
│    ├── .vitepress/theme/custom.css ← 覆盖 VP CSS vars      │
│    ├── package.json + pnpm-lock.yaml                      │
│    └── {getting-started, guide, reference,                │
│         concepts, operations, adr}/*.md                    │
└────────────────────────────────────────────────────────────┘

                          │  pnpm --dir handbook-src run build

┌─ Build 输出 (gitignored) ─────────────────────────────────┐
│  www/handbook/   ← VitePress dist (静态 HTML/JS/CSS)       │
└────────────────────────────────────────────────────────────┘

                          │  CF Pages serve www/ as build root

┌─ 公网 ────────────────────────────────────────────────────┐
│  https://www.apex.fan/handbook/         ← 新手册站           │
│  https://www.apex.fan/                  ← 主站 landing 不变  │
│  https://www.apex.fan/showcase/*        ← 信息图不变         │
│  https://www.apex.fan/docs/*            ← 仍 404 (ADR-005)  │
└────────────────────────────────────────────────────────────┘

与 ADR-005 的关系: ADR-005 把 CF Pages 定位为"静态 + CDN"层; 本 ADR 在不动 ADR-005 hybrid 边界的前提下, 把 www/ 内部从"裸静态"升级为"带 build step 的静态". CF Pages 配置改一行 build cmd, output dir www/ 不变.

与 ADR-006 的关系: ADR-006 §3.1 的 Layer 1 (公网部署面) invariant — "0 硬规则命中" — 现在扩展到包含 handbook-src/. scripts/check_public_safe.py 默认扫描根加入 handbook-src/.


3. Consequences

3.1 · 优势 (vs 平铺 .md 现状)

维度平铺 .md (现状)VitePress (本 ADR)
Sidebar 导航❌ 只有 docs.html 静态目录✅ 内置, 按分组渲染
Search❌ 无✅ 内置 local (Minisearch, 无 SaaS)
Code 语法高亮❌ 浏览器默认✅ Shiki (双主题 light/dark)
Dark mode❌ 无✅ 内置 toggle, 跟随系统
锚点 TOC❌ 无✅ 右侧自动
代码块 Copy❌ 无✅ 右上角自动
移动端响应⚠️ CF 默认✅ 内置 sidebar 抽屉
⌘K palette❌ 无✅ 内置
与主站视觉一致性❌ docs.html 自己一套✅ 继承 index.html DNA

3.2 · 接受的 tradeoff

  • CF Pages build 时间从 0s → ~30s: 每次 push 触发 pnpm install --frozen-lockfile + vitepress build. CF Pages free plan 500 builds/月 + 25min/build 配额内绰绰有余, 但首次 build 会拉 Node 20 + pnpm + ~50MB node_modules
  • handbook-src/ 是新顶层目录: 增加 vault 复杂度, CLAUDE.md §2.2 写权限矩阵 + config.yaml sage-wiki ignore 需同步更新
  • build 失败会卡 deploy: VitePress build error → 整个 www/ 不更新 (含 index.html / showcase/). 风险缓解: PR 阶段先 preview deploy 验证再合 main
  • 额外的运维心智: 内容编辑者要懂 markdown frontmatter + sidebar 配置, 不再是"扔个 .md 进 www/ 就 serve"
  • pnpm-lock.yaml 进 git: 锁版本必要, 但 dependabot 类工具升级 PR 会有噪音

3.3 · 不变的承诺

  • ADR-001 multi-anchor (anchors/<slug>/) 不变
  • ADR-005 hybrid (CF Pages 静态 + 腾讯云 API) 不变
  • ADR-006 4 层防护不变, Layer 1 invariant 扩展到 handbook-src/
  • /docs/* → 404 拦截规则 永久保留
  • docs/internal/ 永远 gitignored
  • scripts/check_public_safe.py + scripts/redact_check.py 双闸前置
  • www/index.html www/changelog.html www/showcase/* 完全不动

3.4 · Invariant impact ★

本变更让以下 invariant 失效:

  • "www/ 是纯静态文件目录, CF Pages 直接 serve, 无 build step" → 失效. 现在 www/ 部分内容 (handbook/) 来自 build 输出. www/site-update-workflow.md 的"编辑 → push → 上线"流程对 handbook 需扩展为"编辑 handbook-src/ → build → push → 上线"
  • "vault 内除 tests/ 外不需要 Node toolchain" → 失效. CF Pages 部署节点和本地开发都需要 Node 20 + pnpm
  • "scripts/check_public_safe.py 默认只扫 www/" → 失效. 需扩为 www/ + handbook-src/

本变更引入以下新 invariant:

  • inv-1: handbook-src/ 内容 0 硬规则命中 (真名 / 飞书 URL / 内部域名). 由 check_public_safe.py --root handbook-src/ 守住, 加进 pre-commit 与 GHA check-public-safe.yml
  • inv-2: www/handbook/ 永远 gitignored (build artifact), 任何 commit 含此路径 = 配置错误
  • inv-3: VitePress 配置不引用 docs/internal/ anchors/<slug>/raw/ cases/ reports/ failure_cards/ 任何路径. 由 handbook-src/.vitepress/config.ts review 守住
  • inv-4: CF Pages build 失败 = 整站 deploy 失败. 缓解策略: 所有 handbook 改动走 PR + preview deploy, main 分支保护

4. Alternatives Considered

方案为什么没选
A · DocusaurusReact + 全套生态, 自带 i18n/版本化/blog/plugin. 30 页规模 overkill, build artifact ~80MB vs VitePress ~40MB, 学习曲线更陡
B · Mintlify (SaaS)trajectory.ai 实际用的就是 Mintlify, 体验对标最近. 致命问题: SaaS 托管, 内容上传到 mintlify.com 服务器, 与 ADR-006 §3.1 "Layer 1 公网部署面由我们 100% 控制" 哲学冲突. 即便公开层也不接受第三方 host
C · 手写 HTML + 共享 sidebar JS视觉一致性最强 (index.html 100% 复用), 零构建依赖. 致命问题: 无 search, 加页要手编 HTML + 维护 sidebar.js, 长期维护成本高
D · 用 /docs/ 路径 + 撤 _redirects 404 规则直觉最自然, 与用户原始意图一致. 致命问题: 违反 ADR-005/006 invariant, 失去"docs/* 永远 404"承诺, 未来手滑加 docs/foo.md 直接漏出. 选 /handbook/ 是路径换 invariant 守住
E · 启用 docs.apex.fan 子域 (独立 CF project)与主站完全解耦, build 失败不影响 index.html. 致命问题: 多一个 CF project + DNS record + SSL cert 维护. 当前 8 篇 + 5 篇新写 + 7 篇 ADR = 20 页规模, 不值得开子域
F · 保留现状0 工作量. 致命问题: trajectory.ai 体验差距持续扩大, 文档可发现性 (search) 持续缺失

5. Migration Plan

详细 Phase 拆分见 writing/handbook-build-plan.md. 总览:

Phase工作入 git预计
0本 ADR + CLAUDE.md §2.2/§11 + config.yaml ignore + site-update-workflow.md5 文件0.5h
1handbook-src/ 脚手架 (package.json + .vitepress/config.ts + index.md)~5 文件1.0h
2主题 DNA 继承 (custom.css 覆盖 VP CSS vars)2 文件1.5h
3内容迁移 + 新写 5 篇 concepts + 1 篇 CLI~20 文件2.0h
4Local search 配置 (Minisearch + CJK termSplitRegex)config.ts 改0.5h
5check_public_safe.py 加 handbook-src/ rootscripts/*0.5h
6CF Pages build cmd + _redirects + sitemap.xml3 文件1.0h
7Preview deploy + 全链路 smoke仅验证0.5h
8dev-log + README + docs.html banner + 上线3 文件0.5h

: ~8h, 建议 2-3 session 拆.


6. 关键反共识立场

6.1 · "上 Mintlify 最省事" — 错

Mintlify 是 trajectory.ai 实际用的 SaaS, 0 配置即得 trajectory 那套 UI. 但省事的代价是 host 主权: 内容文件存在 mintlify.com 数据库, 由他们 build + serve. 即便我们的 handbook-src/ 是脱敏后的公开层, ADR-006 §3.1 Layer 1 invariant 写的是 "由我们 100% 控制" — 这不是性能或成本考虑, 是基于"任何第三方都可能在未来某天改 ToS / 加水印 / 上 ads / 停服" 的反共识立场.

自建 VitePress 是 6h 一次性投入换 永久主权: 内容文件在我们 git, build 在 CF Pages (走 ADR-005 已批准的 host), serve 在 CF Pages, 全链路无 vendor 风险.

6.2 · "用 /docs/ 路径更自然" — 错

/docs/ 是直觉, 但 invariant 不是直觉的. ADR-005/006 落地时, /docs/* → 404 是为了防 docs/internal/ 被 SEO 抓而写的兜底拦截. 即便今天 docs/internal/ gitignored 不在 build 里, 失去拦截规则后, 未来任何手滑 (新人 cp 一份私密文档到 docs/ 当临时草稿 → 不小心 add commit → CF Pages serve) 都会变成公网泄漏.

正确立场: invariant 一旦立就别为短期方便撤. 改路径成本是一次性的 (本 ADR), 撤 invariant 的成本是隐性的 (未来某次手滑被现实抓到).

/handbook/ 不是"妥协方案", 是更准确的语义 — boss 的内容是方法论手册, 不是 API reference.

6.3 · "build step 是过度工程化" — 错

平铺 .md 的"零构建"看起来简单, 但把"无 search / 无 sidebar / 无 dark"伪装成 feature. 实际付出的是用户体验税: 任何想了解 boss 的人打开 user-manual.md 看到一片裸文本, 转头就关.

CF Pages build 30s 是一次性 CI 成本; 用户体验改善是 N×N 次 read 收益. 这不是 over-engineering, 是把成本从"用户每次 read 痛" 转移到 "我们 push 一次小耗时".


7. 何时回看本 ADR

  • 上线 1 周后: handbook 实际访问量 (CF Pages Analytics) + 是否有 search miss/click 数据
  • CF Pages build 失败 ≥ 2 次/月: 触发 ADR 修订, 考虑是否需要拆 docs.apex.fan 子域 (Alternative E)
  • handbook-src/ 文件数 > 60: 触发评估是否需要升级到 Docusaurus (Alternative A) 拿 i18n / 版本化
  • 真名/飞书 URL 通过 CI 进了 handbook-src/: 触发 ADR-006 inv-1 修订, 收紧 pre-commit

ADR-008 · accepted · 2026-06-01 · ADR 体系第 8 个 · VitePress + /handbook/ + 继承主站 DNA · 用路径换 invariant 守住

判断力工程化 · Judgement, Engineered · 主站 · GitHub