AI 写的 HTML 越来越多,版本该怎么管理?我的答案是 Gist

上个月 Anthropic 那位工程 lead ( Thariq Shihipar )抛了个观点:在 agent 场景里,HTML 正在比 Markdown 更能留住人——它有可视化、有颜色、有交互,而 Markdown 输出永远是那一坨线性文本。这事在 HN 和 Reddit 吵得挺凶。我不完全站队,但它确实戳到我两个具体痛点。 痛点一:Markdown 的天花板很硬 我经常让模型写长篇技术文档。写到一定长度就会发现:结构图画不了( mermaid 不是哪儿都渲染,画出来还是那个味儿)、没有明暗主题、目录不联动、代码块想加个复制按钮都得看平台脸色。 而模型现在写单文件 HTML 的能力早就够用了。内联 SVG 、内联 CSS 、内联一个几十行的语法高亮器,一个文件全搞定,双击就能开。 痛点二:这些 HTML 往哪放,又怎么管版本 第二个问题比第一个更烦,而且很少有人提。 模型生成的单文件 HTML 动辄 100+ KB ,而且迭代极其频繁——"主题换成暗色"、"这节展开讲讲"、"这个图标签溢出了",每一轮都是一次全文重写。于是你会遇到:

本地存一堆 index-v2.html、index-final.html、index-final-真的最终版.html 传到静态托管( CF Drop / Netlify drop / S3 / 自建),你永远只有"最新版",改坏了回不去 分享出去的链接是活的。你改完之后,别人看到的和当初讨论的已经不是一回事,而且没人知道变了什么 想对比"上一版到底动了哪",只能人肉 diff 两个 100KB 的文件

这就是我最后选 Gist 的原因:每个 gist 本身就是一个完整的 git 仓库。 git clone https://gist.github.com/.git

于是上面那堆问题一次性没了:每次编辑自动产生一个 revision ,网页上能翻历史,能 clone 回退,能取任意历史版本的 raw 。顺带白嫖的还有:免费不限量、不用备案不用配 CI 、可 fork (别人能拿你的 demo 接着改)、可评论、可 star 、多文件、raw URL 稳定。 我拿自己这几天的东西做了个实测。有一篇 126 KB 的教程,前后改了 4 版,gist 里的 git 记录是这样的: +2069 -0 初版 +346 -18 加了一整章泛型 +189 -4 加了泛型方法一节 +40 -9 修 sidebar 的 sticky 和滚动条

一个"巨型单文件 HTML",在 git 眼里就是正常的增量 diff——每次改了什么、改了多少,一目了然。这跟"HTML 没法做版本管理"的直觉正好相反。 于是有了 gists.page Gist 唯一的问题是:它只给你看源码,不给你看渲染结果。 所以我做了 https://gists.page —— 把 gist id 拼在域名后面,直接看渲染出来的页面: https://gists.page//

原理一句话:Service Worker 拦截请求,从 GitHub API / raw 取内容,按扩展名返回正确的 MIME 。纯静态、没有后端、不存任何内容,跑在 Cloudflare Pages 上。相对路径引用也能解析,多文件 demo 直接传上去就行。你已经有的 gist 也不用动,把 id 贴上去就能看。 光有个网站还不够 模型并不知道这东西存在,更不知道怎么用它。所以仓库里还带了一个 skill ( Anthropic 的 Agent Skills 格式,本质就是一个带 frontmatter 的 SKILL.md,Claude Code 和 Codex 都能加载): https://github.com/zzir/gists.page/tree/main/skills/gists-page 里面写明白了这么几件事:

优先写单文件 index.html,能内联就别拆多文件 发布路径按可用性降级:gh CLI → GitHub MCP → REST API + curl → 实在不行让用户手动去 gist.github.com 更新走 gh gist edit --add,或者 clone 下来 commit + push Gist 是扁平的,没有目录,多文件得先拍平;只有精确的 index.html 会被当默认页 别 curl 预览链接去验证——内容是 SW 渲染的,curl 只能拿到壳页面,要验证得走 GitHub API

这些条目基本都是踩出来的。装上之后,在 Claude Code 里一句 /gists-page 写一篇 xx 教程,图文并茂,发布,它自己写 HTML 、自己建 gist 、自己回一条预览链接;下次说"再加一节",它就 gh gist edit 推上去,链接不变,历史留在 gist 里。 这其实正好接上开头那个 agentic loop 的说法:产出物本身就得是可直接分享、且能沉淀下来的成品,否则每一轮都要人手动导出、找地方托管、再贴回去,还没有历史。 四篇实例 这几天我就是这么让 Claude 写了 2 篇设计模式手册: ZH:

https://gists.page/0152d8bc733b68dad27a477d0b45b3cd/ https://gists.page/8599e4e8ca705edd68521c3e538eca22/

EN:

https://gists.page/ee5d5136cc25c9f0e835308d3422e6e1/ https://gists.page/1f32d84cd2f9bf79c307d51dbe7b047f/

每篇 17–20 张内联 SVG 结构图、明暗双主题、目录联动、代码一键复制。如果当初让它输出 Markdown ,这些图就只能退化成"文字描述一下"。 一个容易混为一谈的点 最近还有个流传的数据,说给 LLM 喂 Markdown 比喂 HTML 省 60–80% token 。这跟上面那个观点不矛盾——模型读的东西用 Markdown 省钱,模型产出给人看的东西用 HTML 信息量大,两个方向的事。 老实说下限制

预览只认最新版。 GitHub API 支持 /gists/{id}/{sha} 取历史 revision ,但 gists.page 现在的 URL 第二段是文件名,还没做版本预览。想看旧版得自己走 raw 或者 clone 。这条我打算改,欢迎提意见 GitHub 网页对大文件的 diff 基本折叠不给看。 100+ KB 的单文件 HTML ,想认真看改动还是得 clone 下来 git diff 必须有 Service Worker 。curl 和爬虫只能拿到壳页面,SEO 别指望 Gist 扁平,没有目录 匿名 GitHub API 60 次/小时/IP ,超了会退到 raw 端点 Gist 里的 JS 跑在 gists.page 这个域上,别往里放密钥

站点源码和那个 skill 都在这里:https://github.com/zzir/gists.page 欢迎拍砖,尤其是 SW 那部分的实现。也欢迎 Fork 和 Star 。