目录

折腾 | 全程浏览器创作博客

本文解决的是个人博客写作链路太依赖本地环境的问题:把文章编辑、数据维护、图片处理和发布触发都尽量放到浏览器里完成,让 Hugo 仍然保持静态站点的简单可靠,同时让日常写作不再被「我现在手边有没有电脑、有没有配好仓库、图片有没有处理完」这些小事卡住。

https://img.philohao.com/blog/2026/05/20260516-01.webp

适用场景

适合已经有 Hugo / 静态博客,但日常更新越来越像「开电脑、拉仓库、修 front matter、压图、传图床、复制链接、提交、等部署」这一整套流水线的人。

如果只是偶尔写一篇长文,本地编辑器当然很舒服;但如果想在午休、通勤、外出时也能补两句月报、加一条书影记录、上传几张图,那么把创作入口搬到浏览器里会轻松很多。它不是要替代 Git,也不是要把 Hugo 变成动态 CMS,而是把最频繁、最容易打断表达的操作前移到网页表单和网页工具里。

背景

我这个站点现在大致有几类内容:普通博文、月报、书影游数据、足迹页面、海报墙。它们底层其实都还是 Markdown 和 YAML,真正发布时也还是 Vercel 拉仓库跑 Hugo 构建,所以「可靠」这件事没有变。

之前麻烦的是创作入口太分散:

  • 写文章要打开本地仓库;
  • 改书影游记录要找到对应的 data/*.yaml
  • 图片要先裁剪、压缩、改名,再上传到图床;
  • 上传完还要把 URL 拼成 Markdown 图片语法;
  • 最后再提交代码,等自动部署。

每一步都不难,但它们连在一起就会变成一种心理阻力。尤其是图片,只要中间多一次「等我回头再处理」,这篇文章很可能就真的回头不见了。

于是这次折腾的目标很明确:让浏览器成为日常内容生产的主工作台。仓库、Hugo、Vercel、R2 这些底层设施继续各司其职,但我平时面对的界面尽量只有两个:Pages CMS 和图片上传器。

核心步骤

1. Pages CMS 管正文和数据

本站的 Pages CMS 配置放在仓库根目录的 .pages.yml。我在里面把文章作为一个 collection 暴露出来,并设置了文件名模板:

1
2
3
4
5
6
7
8
9
content:
  - name: posts
    label: Posts 文章
    type: collection
    path: content/posts
    subfolders: true
    filename:
      template: "{year}/{year}{month}{day}.md"
      field: create

这样新建文章时,文件会自然落到 content/posts/2026/20260516.md 这种年份目录里,不需要我每次手动想路径。front matter 里的标题、描述、日期、分类、系列、标签、目录、评论、草稿等字段,也都变成了表单项。

更关键的是,正文仍然用 Markdown 源码编辑。这样有几个好处:

  1. Hugo shortcode、相对链接、代码块都不容易被富文本编辑器改坏;
  2. 复制进来的图片就是标准 ![alt](url),离开 CMS 也能读;
  3. Git diff 看到的仍然是纯文本,后续排查问题比较安心。

除了文章,.pages.yml 里也把 data/books.yamldata/movies.yamldata/mental_links.yamldata/footprint.yaml 配成了数据编辑入口。也就是说,书影游和足迹这种结构化内容,不一定要回到本地编辑 YAML,直接在浏览器里改字段即可。

2. 图片上传器管图床前的脏活

图片处理单独放在另一个仓库:r2-image-uploader。它是一个部署到 Cloudflare Pages 的小工具,目标不是做一个大而全的图库,而是解决我写博客时最烦的那几件事:排序、裁剪、压缩、命名、上传、复制链接。

现在的流程是:

  1. 在浏览器中拖拽或选择一张 / 多张图片;
  2. 如果是多图,先在待上传列表里调整顺序;
  3. 点击「裁剪并上传」,逐张选择比例,或者跳过裁剪;
  4. 浏览器本地用 Canvas 压缩并转成 WebP;
  5. 按命名规则生成 R2 key,例如 blog/2026/05/hugo-pages-cms-01.webp
  6. 通过 Cloudflare Pages Function 写入 R2;
  7. 返回公开 URL,并同时给出 Markdown、HTML、Hugo figure 等复制格式。

这里最重要的一点是:图片处理尽量发生在浏览器本地。裁剪和压缩不需要额外上传原图到某个服务,也不需要在 Cloudflare 侧引入更复杂的图片处理链路。最终真正写入 R2 的,是已经处理好的 WebP 文件。

3. 用 Markdown 图片链接把两边接起来

图片上传器和 Pages CMS 之间没有做复杂集成,连接方式反而非常朴素:复制 Markdown。

比如上传完成后得到:

1
![全程浏览器创作流程](https://img.philohao.com/blog/2026/05/20260516-01.webp)

然后把它粘贴到 Pages CMS 的正文里即可。这个方案看起来很「土」,但我还挺喜欢,因为它没有额外绑定关系:

  • Pages CMS 不需要知道 R2 的 Access Key;
  • Hugo 不需要知道图片上传器的存在;
  • 图片上传器也不需要写入内容仓库;
  • Markdown 原文里保留的是最终可访问的公开 URL。

工具之间只用一行 Markdown 交接,反而降低了系统整体的耦合度。以后如果 Pages CMS 换了,或者图片上传器重写了,只要 Markdown 图片语法还在,旧文章就不会受影响。

4. 保存后仍然走 Git 和 Vercel

浏览器创作并不意味着绕过 Git。Pages CMS 保存内容后,本质上还是向这个内容仓库提交 Markdown / YAML 变更。后面的发布链路维持原状:Vercel 拉取仓库,执行 Hugo 构建,生成静态页面。

这也是我比较看重的一点:浏览器只是降低写作门槛,不改变站点的基本架构。最终留下来的仍然是一个可以 clone、可以 diff、可以回滚、可以迁移的静态博客仓库。

最终效果

现在写一篇带图文章,大致会变成这样:

  1. 打开 Pages CMS,新建文章,填好标题、摘要、分类和标签;
  2. 打开图片上传器,把要用的截图或照片拖进去;
  3. 排序、裁剪、压缩、上传;
  4. 复制全部 Markdown 图片链接,粘贴回文章正文;
  5. 在浏览器里继续写正文,保存;
  6. 等 Vercel 自动构建发布。

整个过程里,我不需要打开本地图片压缩软件,不需要手动改文件名,不需要登录 R2 控制台,也不需要为了临时补一张图去折腾本地仓库。写作时真正需要关注的东西少了很多:我只要想清楚这篇文章要说什么,再把图片放到合适的位置。

小结

这次折腾的核心不是「上了一个 CMS」或者「做了一个图床工具」,而是把个人博客创作拆成了几个边界清晰的小环节:

  • Pages CMS 负责内容表单化;
  • 图片上传器负责图片进入正文前的处理;
  • Cloudflare R2 负责稳定存储图片;
  • Git 仓库负责保存最终文本;
  • Vercel + Hugo 负责静态构建和发布。

这样拆完之后,日常写作轻了很多,底层也没有变得不可控。对我来说,这大概就是个人站点最舒服的状态:平时像在线笔记一样顺手,出问题时又能回到 Git 和 Markdown 这种朴素、可迁移、好排查的东西上。

后续如果继续优化,可能会考虑给图片上传器加更细的 preset、给 Pages CMS 的数据字段补更多说明,或者把常用文章模板整理得更完整。但当前这个版本已经足够解决一个很实际的问题:从「想写」到「发出去」之间,少一些摩擦。

参考资料

(2026-05-16@深圳)