项目文档搬上网站以后,常会悄悄长出两份正文。
仓库里有 Markdown,网站目录里又有一套。有人改了前者,忘了后者;有人为了修网站链接,直接改生成文件。过几个月,两边都像真的,谁也不敢删。
dsh-doc-site-sync 给 DeepSeek Harness 定了一条很硬的规矩:仓库 Markdown 是唯一可编辑来源,文档网站只是一次可以重建的投影。
1. 网站页面由一份 manifest 决定
公开哪些文档、放在哪条路由、侧栏叫什么,不靠脚本扫描整个仓库猜出来。
这些信息写在 website/docs.ts[1] 里。每个页面条目会说明:
source 源 Markdown
route 网站路由
label 导航文字
sidebar 属于哪个侧栏
section 位于哪个章节
order 排序
sourceAliases 必要时保留的旧锚点这份清单把“仓库里有一篇文档”和“它应该出现在公共网站”分开。内部说明可以继续留在仓库,不必意外被网站收进去。
2. 投影脚本具体做什么
运行文档流程时,project-doc-site.ts[2] 读取 manifest 和源 Markdown,把网站需要的内容写进:
website/.generated/随后 VitePress 从这个临时目录构建站点。
投影过程中,它不只是复制文件。相对链接指向 manifest 内的另一篇文档,会改写成网站路由;指向仓库里存在、但没有公开到网站的文件,会改成 GitHub 源码链接;图片会复制到生成目录;找不到目标的相对链接直接报错。
整件事和编译差不多:源文件、页面清单和链接规则是输入,.generated 是构建产物。产物坏了,回头改源文件或生成器,不进输出目录打补丁。

3. 中英文路由怎么排
DeepSeek Harness 的双语文件放在一起:
foo.md
foo.zh.md
foo.i18n.yaml中文被投影到站点根路由,英文放在 /en/。源仓库不再另建 docs/zh/ 和 docs/en/ 两棵目录。
正常页面用 pairedPages() 从同一组源文件生成两种语言。确实只有一种语言的页面,才用 mirroredPages() 做有意回退。回退是显式选择,不是发现译文缺了就悄悄拿另一种语言顶上。
源文件怎么存,网站路由怎么排,两件事就此分开。以后调整站点语言结构,不必搬动整个文档库。
4. 新增一篇文档时会发生什么
假设要增加一个安装指南,完整动作是:
新增 install.md
新增 install.zh.md
新增 install.i18n.yaml
在 website/docs.ts 登记页面
运行投影脚本
VitePress 构建 website/.generated
检查双语配对、链接和站点构建生成目录不提交,也不手工编辑。页面改名时,源文件、manifest 和入站链接要一起改;旧 fragment 需要兼容,就在 manifest 里写明确 alias。
这比“复制一份到网站目录”多了几条规矩,却少了一份长期维护的正文。
5. 怎么用,以及哪些部分不能硬搬
dsh-doc-site-sync[3] 是仓库内部 Skill。可以这样让 AI 学它的流程:
请阅读 deepseek-harness 的 dsh-doc-site-sync。
为我的项目设计“Markdown 是唯一原稿、网站是生成投影”的文档流程。
先列出页面 manifest、生成目录、链接改写和双语路由规则,再决定需要哪些脚本。如果你的站点本来就直接读取仓库 Markdown,没必要再造一层 .generated。这套方案适合源目录结构与公开站点结构不同、需要筛选页面、改写链接或维护双语路由的项目。
6. 自己实现一个最小版本
先写一份页面清单,每页只放 source、route 和 title。脚本读取清单,把文件复制到临时目录,并做三项检查:源文件存在、站内链接有目标、同一路由不能重复。
第二步再加资源复制和链接改写。第三步才考虑双语配对、旧锚点和侧栏排序。
有一条最好从第一天就定下:生成目录随时可以删除重建,不能成为编辑入口。只要有人需要手改生成文件,说明源文件、manifest 或生成器少表达了一件事。
7. 我的判断
文档网站拖到后来难维护,往往是大家心里各认一份“原稿”,VitePress 配置反倒排在后面。
dsh-doc-site-sync 把这件事说得很死,也做得很干净:正文只在仓库里改,网站目录用脚本重建。失去一点临场改页面的方便,换来的是半年以后还能回答“这句话到底该去哪改”。
引用与来源
[1] `website/docs.ts`
https://github.com/deepseek-ai/deepseek-harness/blob/master/website/docs.ts
[2] `project-doc-site.ts`
https://github.com/deepseek-ai/deepseek-harness/blob/master/scripts/project-doc-site.ts
[3] dsh-doc-site-sync
https://github.com/deepseek-ai/deepseek-harness/tree/master/.agents/skills/dsh-doc-site-sync
夜雨聆风