这几天基本都在折腾这个博客。
原本只是想把 Hugo 博客改得更像 Claude Blog 一点,结果一路从主题、字体、封面、移动端比例、导航、标签,到多语言页面、GitHub 子模块和服务器同步都摸了一遍。最后回头看,所谓博客优化,其实不是某一个按钮、某一段 CSS、某一张封面图的事,而是把一整套写作和发布体验慢慢拧顺。
从主题开始
最开始的方向是找一个更接近 Claude Blog 气质的主题。自己在 PaperMod 上一点点仿,确实可以,但很容易越改越像补丁堆。后来找到了 LoveClaude 这个主题,视觉骨架已经比较接近想要的效果,于是博客从 PaperMod 切到了 LoveClaude,再用站点自己的覆盖层去做 nouo 的细节。
这一层最大的收获是:主题源码和自己的覆盖样式要分清楚。主题负责基础结构,自定义文件负责站点气质。否则每改一个细节都去动主题文件,后面就很难判断问题到底来自上游主题、自己覆盖,还是 Hugo 构建产物。
后来为了改文章列表的默认视图,还碰到了子模块权限问题。themes/LoveClaude 原来指向上游仓库,我本地能改,但不能直接推到别人的仓库。最后的做法是 fork 一份到自己的 GitHub,把 .gitmodules 指向可写的 fork,再把主题改动和主仓库指针分别提交。这个过程有点麻烦,但把后续维护路径打通了。
字体这件小事并不小
字体是这轮优化里最折腾的一块。
一开始以为只要在 CSS 里写上 Anthropic Sans、Anthropic Serif,页面就会有 Claude 那种味道。后来发现不对:如果没有真正加载字体文件,浏览器只是看到一个不存在的名字,然后继续回退到系统字体。于是补了 @font-face,让英文、数字、标点和代码真正走 Anthropic 的 Sans、Serif、Mono。
但中文又是另一回事。Anthropic 字体本身不包含中文字形,所以中文一定会继续 fallback。这里来回调了好几版:先是希望全站统一 Claude 字体,后来发现中文落到黑体会和文章气质不一致;再切到宋体,又发现移动端很多设备没有 Songti SC,CSS 写了也不会真的生效。
最后比较稳的方案是:
英文和代码:Anthropic Sans / Serif / Mono
中文阅读:宋体或思源宋体系 fallback
移动端中文:自托管 Noto Serif SC 兜底
还踩了一个缓存坑:字体文件第一次上线时,Cloudflare 缓存了裸路径的 404。源站明明已经有文件,用户请求却还命中旧 404。最后给字体 URL 加了版本号参数,让新 CSS 请求新的地址,问题才彻底闭环。
这件事提醒我,字体不是“写一个 font-family”就完了。字体文件是否存在、是否允许跨域、是否包含中文字形、移动端有没有系统字体、CDN 是否缓存旧响应,都可能让视觉结果和 CSS 想象完全不同。
图片和封面
另一个重点是封面。
我一开始想做类似 Claude Blog 的配图系统,甚至试过用 SVG 生成几张“极简卡片版”样张。效果不能说完全不能用,但明显还不够成熟,像普通流程图多过像文章头图。这个方向暂时先放下,后面如果继续做,应该先拆参考风格,再做模板,而不是临时画一张凑数。
现在更实用的方案是:文章默认走本地图片池,发文脚本创建文章时随机选一张封面并写进 front matter。这样图片跟文章一起进仓库,迁移和回滚都可追踪。
这轮也确认了一条原则:普通个人博客文章配图,默认放本地更稳。图床可以作为备选,但不能把文章内容依赖在一个随时可能防盗链、403、改规则的外部服务上。HostDZire 测评那篇就是例子,图床直链下载会拿到 403 占位图,必须带正确 Referer 才能拿到真实 WebP。最后把四张测试图保存到本地,文章也改成本地路径,线上验证才算放心。
6 月 20 日又补了一点小修:随机封面脚本会避开最近已经用过的图片,尽量减少连续几篇文章撞封面的概率。它不是视觉体系的大改,但对一个文章越来越多的博客来说,这种小自动化能少掉不少重复检查。
移动端不是桌面缩小
移动端这轮也改了很多。
有些问题看起来像“没同步”,实际是移动端还在吃旧的断点规则。比如首页 hero 在手机上仍然占满一整屏,最新文章被压到首屏下面,看起来就像桌面改了、手机没改。后来又反过来,移动端合适了,桌面端位置却感觉上移过头。最后干脆用 PERSONAL BLOG 作为锚点,按视口高度一点点量:
移动端:hero 下移,首屏更饱满
桌面端:hero 上移后再回落一点
这里最有意思的是 svh 和 lvh。移动端浏览器有地址栏,100svh 和 100lvh 不是一回事。想让首页在手机上真的占满一页,不能只看桌面浏览器模拟出来的高度,要看实际移动视口下下一段内容从哪里开始。
首页导航也顺手重新梳理了一遍。桌面端按原主题位置保留,移动端把“文章 / 时间线 / 标签”做成竖排,填补首屏空白。后来又修过桌面端误变横排、位置偏移、按钮组不靠右、footer 徽章换行等问题。每一个都不大,但叠在一起,手机打开博客的感觉会明显稳很多。
今天还把文章列表页的分页补完整了。原来筛选和分页是两套状态,点到第二页后再筛标签,很容易残留旧页码。现在筛选会重新计算分页、回到第一页,分页切换后也会滚回列表顶部。顺手修掉了二级页面顶部导航的 active 遮罩问题,避免当前页高亮把 header 盖出一层不自然的暗块。
语言切换和英文静态页
6 月 20 日最大的变化是多语言。
一开始的想法是做一个语言切换器,让页面能在中文和英文之间切。最初版本偏客户端翻译:前端调用同源 /api/translate,再由 nginx 代理到翻译接口。这样浏览器只连自己的域名,CSP 也更容易收束。后面发现这条路适合临时阅读,不适合长期维护文章:翻译结果不可控,SEO 和分享也都不如真实静态页稳。
最后改成 Hugo 的静态双语结构:中文还是默认路径,英文走 /en/,文章、归档、搜索、首页文案、菜单、上一篇下一篇、相关文章、目录、阅读时间和字数这些界面文本都补了英文版本。head 里也加了 hreflang 和 x-default,让搜索引擎知道中英文页面的关系。
语言选择也从“前端猜一次”变成了几层配合:
Hugo 生成中英文静态页
导航中的语言按钮跳到对应翻译页
nginx 按浏览器语言给首次访问者选择默认语言
用户手动选择后用 cookie 记住
head 里的 prepaint 脚本提前兜底,减少首屏语言闪烁
这里的经验和发布链路很像:语言不是一个按钮就结束。URL 结构、静态内容、浏览器语言、手动选择、缓存、SEO 标记和首屏渲染要一起闭环,访问体验才会像一个真正的双语站点,而不是临时翻译层。
内容和标签
除了主题本身,也顺手把内容结构整理了一轮。
这几天新增和整理了几篇文章:VPS 常用脚本备忘录、HostDZire 测评、香港 Lightlayer VPS 测评、爱沙尼亚 eSIM 指南、家庭影音库自动化。写完后又把标签重新收束成几类:
博客
折腾
VPS评测
建站机
线路机
这个动作看起来只是 front matter,但对博客长期维护很重要。标签太随意,最后会变成一堆相似词;标签太少,又失去检索意义。现在的分配比较清楚:建站过程归“博客”,工具脚本、eSIM 和家庭影音库归“折腾”,HostDZire 测评归“VPS评测”和“建站机”,Lightlayer 测评归“VPS评测”和“线路机”。
今天还顺手把几篇 VPS 测评的写法统一了一遍。单位写法、冗余感想、段落长短都收紧后,同类文章放在一起读会更像一组资料,而不是每篇都临时起一个格式。
发布链路也要验证
还有一类问题不是代码,也不是样式,而是“我明明推了,为什么看起来没变”。
这轮反复确认了几层:
本地 HEAD
origin/main
GitHub 远端引用
服务器 systemd 同步
线上 HTML/CSS 指纹
Cloudflare 或浏览器缓存
有时候 GitHub 已经更新,服务器定时任务还没拉;有时候服务器已经发布,浏览器缓存还在;有时候线上 HTML 已经换了新 CSS 指纹,但某个字体裸路径被 CDN 缓存了旧 404。还有一次 Chrome 普通窗口会把 nouo.net 裸地址跳到另一个域名,而无痕窗口正常,最后确认是 Chrome 对精确 URL 缓存了错误跳转。
这些都说明一件事:发布不是 git push 结束。对静态站来说,真正的结束是线上页面加载了新 HTML、新 CSS、新图片,并且关键资源都返回 200。
小结
这轮优化之后,博客大概变成了我更想要的样子:
- 主题换成 LoveClaude,并保留自己的覆盖层;
- 字体接入 Anthropic 系列,中文 fallback 更稳定;
- 发文脚本能随机配本地封面;
- 移动端首页、导航、footer、文章列表分页和二级页头部更像一个完整设计;
- 中英文静态页面、语言选择、nginx 默认语言和
hreflang关系初步闭环; - 标签体系和同类文章格式被收束;
- 子模块、远端、服务器同步和线上验证也更顺。
折腾博客很容易陷入一个循环:改一点,看一眼,不满意,再改一点。它不像写业务功能那样有清楚的完成线,但每次把一个小问题查到底,站点就会少一点毛边。现在这个博客还不算最终形态,不过至少已经从“能用”往“顺手、耐看、可维护”走了一步。



