这个博客是怎么搭起来的

我一直想有一个自己的博客。不是那种用现成主题、五分钟搭好的博客,而是一个每一行 CSS 我都知道为什么这么写的博客。

起点

Simon Willison 的博客是我一直以来的参考。内容即界面,没有多余的东西——没有侧边栏小部件、没有社交分享按钮、没有评论区。打开页面,只有文章。

我想做类似的东西,但有几个自己的偏好:

  • 全站等宽字体。JetBrains Mono,我喜欢它干净利落的字形
  • 不依赖任何框架。GitHub Pages 原生支持 Jekyll,但在 Windows 上装 Ruby 很痛苦。与其和工具链搏斗,不如回到最原始的方式
  • Markdown 写作。不想手写 HTML,但也不想为了预览等 30 秒的构建

技术路线

最开始尝试了 Jekyll。本地跑不起来,每次改 CSS 都要靠想象,改完 push 上去等 GitHub Pages 构建才知道效果——这个反馈循环太慢了。

后来改成了纯 HTML。所有的 .md 文件用 Python 脚本转换成 HTML,本地 python dev.py 启动一个服务器,保存文件后浏览器自动刷新。零构建时间。

几个关键的库:

markdown          # Markdown -> HTML
Pygments          # 代码语法高亮
python-frontmatter # 解析文章元数据

加起来不到 100 行的 build.py,做了三件事:

  1. 读取 posts/*.md,解析 frontmatter(标题、日期、类型)
  2. 转换成 HTML,套上模板
  3. 生成首页文章列表和搜索索引

搜索用的是纯前端方案:构建时生成 search.json,页面上一段 50 行的 JS 做即时检索。不需要任何后端。

三种内容类型

我不总是写长文章。很多时候只是记录一下今天做了什么,或者分享一篇读到的好东西。所以设计了三种内容类型:

类型 用途 例子
Article 正式长文 就是这篇
Note 每日小结 今天修了三个 bug,学了两章 Rust
Link 资源分享 推荐文章 + 简短评论

首页会展示所有类型的全文,按时间倒序排列。长文章底部有一个 Permalink 链接。

设计

配色是在路过麦当劳的时候定下来的。麦当劳门店那种红、金、暖灰的组合意外地好看。

  • 主色 #DA291C(麦当劳红)——侧边栏、链接、按钮
  • 金色 #FFC72C——代码块左边框
  • 暖灰 #E5E1DC——页面背景
  • Header 用了 #2D2D2D 深色,和灰色背景拉开层次

整个过程是聊出来的——我描述想法,Claude 帮我写代码。CSS 调了五六版才到现在的状态,中间踩了不少坑:

  • 全站等宽字体导致中文巨丑,最后加了 HarmonyOS Sans 作为中文字体回退
  • 自动刷新一开始用时间戳比对,结果是死循环——页面永远在刷新。改成版本号机制才修好
  • 首页展示全文后长文章太占地方,试了折叠展开的方案,JS 莫名其妙不生效,最后干脆去掉,用侧边栏的 All Posts 列表来导航

数学公式

文章里可以写 LaTeX 数学公式,用 MathJax 渲染。行内公式 $E = mc^2$ 和块级公式都支持:

$$ \int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi} $$

只在包含公式的页面才加载 MathJax,不浪费带宽。

部署

整个博客是一堆静态 HTML 文件,托管在 GitHub Pages 上。更新流程:

python new.py              # 新建文章
# 编辑 posts/xxx.md
python build.py            # 构建
git add . && git commit -m "新文章"
git push                   # 上线

从写完到上线不超过一分钟。

之后

这个博客会持续演进。目前想加的东西:

  • RSS feed
  • 文章标签(也许)
  • 暗色模式(也许)

但大概率不会加评论系统。保持简单本身就是一种功能。