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

发布于

上个月 Anthropic 的工程主管 Thariq Shihipar 提出了一个观点:在 agent 场景中,HTML 比 Markdown 更能留住人——因为 HTML 有可视化、有颜色、有交互性,而 Markdown 输出的内容永远是那一坨线性的文本。这一观点在 Hacker News 和 Reddit 引发了激烈的讨论。我不完全站队,但确实触及了我两个具体的痛点。

## 痛点一:Markdown 的天花板很硬

我经常让模型写长篇技术文档。写到一定长度时就会发现:结构图画不了(mermaid 不是在所有地方都能渲染,最终效果还是那个味儿),没有明暗主题,目录不联动,想在代码块上加个复制按钮还得看平台的脸色。

而模型现在写单文件 HTML 的能力早就足够用了。内联 SVG、内联 CSS以及内联一个几十行的语法高亮器,所有内容都可以放在一个文件里,双击就可以打开。

## 痛点二:这些 HTML 往哪放,又怎么管版本

第二个问题比第一个更烦,而且很少有人提到。

模型生成的单文件 HTML 往往超过 100 KB,而且**迭代极其频繁**——“换成暗色主题”、“这一节再展开讲讲”、“这个图标签溢出了”,每一轮都涉及全文重写。于是你会遇到:

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

**这就是我最终选择 Gist 的原因:每个 gist 本身就是一个完整的 git 仓库。**

```bash
git clone https://gist.github.com/<gist_id>.git
```

这样一来,上述问题都迎刃而解:每次编辑都会自动生成一个修订版,网页上能够翻看历史记录,可以克隆回退,也能获取任意历史版本的原文。顺带着还有:免费、不限量、不需要备案、不用配置 CI、可以 fork(别人可以在你的 demo 基础上继续修改)、可以评论、可以点赞,还支持多文件,原始 URL 稳定。

我拿这些天的实验做了个实测:有一篇 126 KB 的教程,前后修改了 4 版,gist 中的 git 记录如下:

```plaintext
+2069 -0 初版
+346 -18 加了一整章泛型
+189 -4 加了泛型方法一节
+40 -9 修 sidebar 的 sticky 和滚动条
```

对于一个“巨型单文件 HTML”来说,在 git 中就是正常的增量 diff——每次改了什么、改了多少,一目了然。这正好反驳了“HTML 没法做版本管理”的直觉。

## 于是有了 gists.page

Gist 唯一的问题是:它只能查看源码,而不能查看渲染结果。

所以我做了 [gists.page](https://gists.page/)——在域名后面拼上 gist id,就可以直接看到渲染后的页面:

```plaintext
https://gists.page/<gist_id>/
```

原理很简单:Service Worker 拦截请求,从 GitHub API/raw 获取内容,然后根据扩展名返回正确的 MIME 类型。**它是纯静态的,没有后端,也不存任何内容**,只在 Cloudflare Pages 上运行。相对路径引用也能正常解析,多文件 demo 直接上传即可。你已有的 gist 也不用动,把 id 贴上去就能查看。

## 光有个网站还不够

模型并不知道这个东西存在,更不知道如何使用它。所以仓库里还附带了一个技能(Anthropic 的 Agent Skills 格式,本质上是一个带 frontmatter 的 [SKILL.md](http://skill.md/) ,Claude Code 和 Codex 都可以加载):

[https://github.com/zzir/gists.page/tree/main/skills/gists-page](https://github.com/zzir/gists.page/tree/main/skills/gists-page)

里面说明了几个要点:

- 优先使用单文件 `index.html`,能内联就别拆成多文件。
- 发布路径按可用性降级:`gh` CLI → GitHub MCP → REST API + curl → 如果实在不行就让用户手动去 [gist.github.com](http://gist.github.com/)。
- 更新时使用 `gh gist edit --add`,或者先克隆下来提交并推送。
- Gist 是扁平的,没有目录,多文件需要先扁平化;只有精确的 `index.html` 会被当做默认页。
- **不要用 curl 预览链接去验证**——内容是通过 SW 渲染的,curl 只能获取到外壳页面,验证需要通过 GitHub API。

这些条目基本上都是踩出来的。装上之后,在 Claude Code 中输入一句 `/gists-page 写一篇 xx 教程,图文并茂,发布`,它就会自己生成 HTML、自动创建 gist,并返回一个预览链接;下次说“再加一节”,它就会用 `gh gist edit` 进行推送,链接不变,历史保留在 gist 中。

这其实正好契合了开头提到的 agentic loop 的说法:**产出物本身就得是可直接分享的成果,否则每轮都要人手动导出、寻找存放位置再回贴,不留下历史。**

## 四篇实例

这几天我让 Claude 写了两篇设计模式手册:

**中文:**
- [https://gists.page/0152d8bc733b68dad27a477d0b45b3cd/](https://gists.page/0152d8bc733b68dad27a477d0b45b3cd/)
- [https://gists.page/8599e4e8ca705edd68521c3e538eca22/](https://gists.page/8599e4e8ca705edd68521c3e538eca22/)

**英文:**
- [https://gists.page/ee5d5136cc25c9f0e835308d3422e6e1/](https://gists.page/ee5d5136cc25c9f0e835308d3422e6e1/)
- [https://gists.page/1f32d84cd2f9bf79c307d51dbe7b047f/](https://gists.page/1f32d84cd2f9bf79c307d51dbe7b047f/)

每篇文章包含 17–20 张内联 SVG 结构图、明暗双主题、目录联动、代码一键复制。如果当初让它输出 Markdown,这些图只能退化成“文字描述一下”。

## 一个容易混为一谈的点

最近有一个流传的数据,说给 LLM 输入 Markdown 比输入 HTML 能节省 60–80% 的 token。这跟上面提到的观点并不矛盾——**模型读取的内容用 Markdown 省钱,模型输出给人看的内容用 HTML 信息量更大**,这是两个方向的问题。

## 老实说下限制

- **预览只认最新版**。GitHub API 支持 `/gists/{id}/{sha}` 获取历史修订版,但 gists.page 现在的 URL 第二段是文件名,还没有实现版本预览。想查看旧版只能自己走 raw 或者克隆。这个我打算改,欢迎提出意见。
- **GitHub 网页对大文件的 diff 基本折叠,无法查看具体改动**。对于 100+ KB 的单文件 HTML,想认真查看改动还是得克隆下来使用 `git diff`。
- 必须有 Service Worker 。curl 和爬虫只能获取到外壳页面,SEO 别指望。
- Gist 是扁平的,没有目录。
- 匿名 GitHub API 每小时 60 次/IP,超过会降级到 raw 端点。
- Gist 中的 JS 运行在 gists.page 这个域上,别往里放密钥。

站点的源码和那个 skill 都在这里:[https://github.com/zzir/gists.page](https://github.com/zzir/gists.page)
欢迎提出建议,尤其是 SW 部分的实现。也欢迎 Fork 和 Star 。

---

原文链接:[点击查看](https://www.v2ex.com/t/1231197)

评论

暂无评论。

0.068243s