AstroPaper 博客改造日志 #ai
基于 AstroPaper 模板搭建了这个博客。这篇日志记录对它的改动,按日期倒序,随提交更新。
2026-07-28
全站只保留一个日期字段
原本有 pubDatetime、modDatetime、timezone 三个日期相关字段,排序读前者、页面显示读后者——两者能不一致,首页顺序因此是错的,一直没人发现。
收敛成唯一的 pubDatetime,精确到分钟,格式与页面上显示的完全一样("YYYY-MM-DD HH:mm"),按站点时区解读,写 frontmatter 不用再手算 UTC 偏移。schema 里加了防呆:不加引号会被 YAML 解析成时间戳、格式写错会直接构建失败,并提示正确写法。
手机端发短文,CI 补上兜底
短文现在可以从手机发:iOS 快捷指令直接调 GitHub 的 contents API 提交文件,推到 main 后 Cloudflare Pages 自动构建。这条链路和它的三个坑单独写了一篇——从手机发一条短文。
为它给 CI 加了两样东西:
push到 main 也触发。原来只在 pull request 时跑,直推完全没有校验;而手机端不会先本地构建,CI 是唯一的拦截点- 内容收录检查。找出
src/content下不以_开头、又不是.md/.mdx的文件就让构建失败。手机端文件名一旦混进空格,URL 会被截断、扩展名丢失,GitHub 照样返回201,但文件不匹配内容集合的 glob,构建静默忽略它——发出去了,站点上什么都没有
撤掉 remark 管线,回到 Astro 7 原生引擎
7 月 21 日那条写着「本站重度依赖 remark-toc、remark-collapse」,这个判断是错的。两个插件的触发条件都是标题为 “Table of contents”,而全站没有任何一篇文章写过这种标题——目录早就改由组件从 headings 生成。它们从配上去那天起就是空转的。
删掉三个依赖和整段 markdown.processor 配置,渲染交还给 Astro 7 原生的 Satteri 引擎。逐页比对构建产物,本以为零差异,结果发现一处真实变化:源文件里的直引号 "理解",旧管线把前后两个都渲染成右弯引号 ”理解”,Satteri 正确配对成 “理解”。全站 37 处开引号因此被修正——顺手修了一个一直没注意到的中文排版 bug。
清掉上一轮重构的残留
上次大改删了标签、返回按钮等六项功能,扫尾没做干净。按「零引用」标准过了一遍,删掉 ResponsiveTable.astro、两个图标、Main.astro 两个从没被传过的 props、若干 i18n 键,以及 Layout.astro 里指向不存在的 favicon.ico 的 <link>(每次访问白吃一个 404)。
两个 schema 字段一并收掉:文章的 author 五篇都写了但从没被读取(渲染时用的是站点配置),短文的 title 从不渲染。Datetime.astro 里写死的 .locale("zh-cn") 也挪进了 i18n。
代码块换配色,顺带修掉一条常驻的滚动条
原来的 min-light / min-dark 饱和度太高——统计下来全站出现最多的是紫色 #B392F0(164 次),其次是亮红和橙。这些颜色铺在大段中文里很跳。换成 vitesse-light / vitesse-dark,低饱和偏暖,跟纸感底色是一路的。底色也不再取主题自带的纯白 / 纯黑,改用单独的 --code-background,只比页面底色深一档。
顺带修了个一直存在的 bug:行内代码的 0.15em 左右外边距没有在代码块里被重置,叠在 flex-basis: 100% 上,导致任何长度的代码块都恒定溢出 0.3em,底部永远挂着一条横向滚动条。
文章的元数据归位
两件相关的事。
标题旁的 AI 角标。 新增 aiGenerated 字段,为真时在标题右侧渲染一个很轻的 AI。它不写进 title 字符串,所以 <title>、RSS 标题和搜索索引都不受影响。不设默认值——AI 写的和人写的都要显式表态,免得默认值把哪一边标错。
更新记录搬进 frontmatter。 原本是正文里手写的 <details> + Markdown 表格,四列在手机上没法看,折叠三角接不了主题色,内容还会被 pagefind 当正文索引(搜「初次生成全文」能搜出一堆)。改成 updates 数组由组件渲染:日期复用 pubDatetime 的校验器,操作是枚举,说明校验非空,写错构建即失败。位置也从文末挪到标题下方,和日期、目录并排成一行。
这两个折叠块都没有用 <details>:它的按钮和面板必须是父子,面板要整行展开就得让整块变成整行宽,按钮会被挤到下一行。改成按钮 + 面板两个兄弟元素,外层 display: contents,按钮留在行内不动。
列表页的层级与留白
首页噪音的根源是简介和标题同色,两者等重,整页读起来是一片。新增比 muted-foreground 更弱的 --faint 色标,层级理顺成三级递减:
标题 #2c2a26
简介 #5f5a52
日期 #8a8377
短文的字号也归了位。它原本套着 app-prose,用的是文章详情页的阅读态字号(17/18px、行高 1.8),放进索引列表后比旁边的简介大 2px、松 6px——同一条时间线上混着两套字号。压回 16px。
其余几处:
description加max(45)校验,六篇全部重写。原来 44~126 字,现在 31~40,时间线上都是一行- 时间线竖线原本是容器的左边框,边框必然贯穿整个容器、从第一个圆点上方探出一截。改成绝对定位的竖条,从圆心起画
- 页尾的分页和统计合并成一行,统一到 14px 弱化色;分页只留箭头,去掉「上一页 / 下一页」字样
perPage从 4 提到 10(短文 15)。原来它和perIndex都是 4,列表页跟首页显示的一样多,翻页毫无意义
又减掉两样
站点图标。一直用着 Astro 模板自带的 logo,试了好几轮替代方案都不满意,索性整个移除,标签页显示浏览器默认图标。
页脚的 GitHub 与邮箱。两个链接不值得一套组件 + 配置 + 类型 + 图标资源的机制,直接写在关于页的正文里就够了。
2026-07-21
三个列表页统一为时间线
原本「首页 / 文章列表 / 归档」三处入口各说各话。合并为一条按时间倒序的时间线:首页文章与短文(新增的 notes 集合)混排,文章显示标题,短文直接内联展开正文。文章页改成参考 Lapis 的年份时间轴,独立归档页(/archives)连同相关配置一并删除——文章页本身就是按日期归档的视图。
列表页(含关于、搜索)统一去掉面包屑、页面大标题和描述,进页直接是内容。
升级到 Astro 7
Astro 6.4.8 → 7.1.1,@astrojs/mdx 5 → 7,sitemap、rss 跟到兼容版本。当时为了稳妥保留了 remark 管线(一周后发现它本就是空转的,见上)。升级前就存在的 tailwindcss() Vite 插件类型报错,随 Vite 8 对齐后自动消失。
i18n 精简与模板残留清理
i18n 原本用 import.meta.glob 动态扫描语言目录,对两种语言来说是过度设计,改为静态 import。硬编码在组件里的几处文案(首页「全部文章」、代码块「复制 / 已复制」)也收回 i18n,内联脚本通过 data-* 拿翻译值——从此「改文案 = 只改 i18n」才真正成立。
模板残留一并清掉:Docker 三件套、commitizen 配置、上游 CHANGELOG 与 Lighthouse 徽章、.github/ 下的开源协作模板和仍指向原作者的 FUNDING.yml。另外新增了 docs/config-map.md——一张「想改 X 该去哪个文件」的对照表,解决配置分散在多处不好找的问题。
文章目录与导航栏
目录数据来自 render() 返回的 headings,构建期生成,不在客户端解析 DOM。桌面端在正文右侧悬浮并随滚动高亮当前章节,移动端在正文顶部内联折叠。只列 h2/h3,标题少于两个不显示。
导航栏原本把「去页面」和「就地操作」混在一起——文章、关于是文字,归档却是图标,移动端又换成另一套网格。重新按「导航是文字、工具是图标」分组,桌面端与移动端共用同一套结构。
2026-06-22
字体 · Noto 全家族与中文分包
字体折腾了两个月,最终定在 Noto 全家族:正文 Noto Serif + Noto Serif SC,代码与等宽数字 Noto Sans Mono,全部自托管在 public/fonts/,零外部请求。
中文用 unicode-range 分包成 101 个 WOFF2,浏览器按页面实际出现的字符只下载对应分片。完整字库约 5.75 MB 是服务器上的总量,不是单页下载量。方案细节和量化对比另有一篇:中文网站自托管变量字体方案。
字体 CSS 一度通过全局样式的 @import 加载,被 Tailwind 展开后触发 @import must precede all other statements,最终改为在 Layout.astro 的 <head> 里加载三份同源样式表。
2026-05-30
文章页脚本幂等化
启用客户端路由后,来回切页会重复插入 DOM、重复绑定事件。把脚本改成「可重复执行但结果不重复」:进度条用固定 ID 复用,监听器重绑前先移除旧实例,标题锚点和代码块按钮仅在缺失时插入。
模板内容下线
5 篇 AstroPaper 模板文章全部转为草稿并移出 src/content/posts/,只留在 docs/templates/ 作参考。公开页面从 23 页收缩到 14 页,搜索索引也随之只保留真正对外的内容。
README 从原模板说明重写为这个博客自己的定位与目录结构。构建脚本也修了:以前 pnpm build 会把 Pagefind 索引再拷回 public/,把产物写进源码目录,现在只保留在 dist/。
2026-05-29
字体 · 在体积和一致性之间反复取舍
一度移除本地中文字体、让各平台回退到系统字体,最轻,但不同系统的中文观感差异太大,也失去了想要的宋体阅读感。之后尝试用 Fontsource 引入,体积降到约 3.06 MB,但直接引用 node_modules 内部路径不够稳。
2026-05-25
移除分享组件
删掉文章页的「分享这篇文章」——Twitter/Facebook 等平台国内基本不用,浏览器自带复制链接足够了。连带清掉 ShareLinks.astro、相关配置与类型、i18n 键,以及四个纯分享用途的 SVG。
顺手把页脚的「版权所有 保留所有权利」改回英文——中文法律措辞放在个人博客上太突兀。
配置修正与本地编译
修正两项残留的模板配置(profile 和 editPost.url 仍指向原作者),About 页从英文模板介绍重写为个人标识。
本地编译一度因构建阶段需要访问外部资源而失败,关闭了动态 OG 图片并删除相关路由与工具函数,构建链路缩短,结果回到 0 errors / 0 warnings / 0 hints。
2026-05-22
首页与归档布局
首页大删减:去掉 hero 介绍段落、RSS 图标、社交链接,不再区分「精选」和「最近」,打开即见文章列表。归档页从完整卡片改为紧凑单行(左侧 MM-DD,右侧标题)。
2026-05-21
中文本地化与字体起点
新建 zh.ts,逐条翻译导航、文章页、分页、页脚、404 等全部 UI 文案,默认语言切到 zh,日期引入 dayjs 中文 locale。删除 _releases、_color-schemes 两个模板目录。
字体是这个博客改动次数最多的部分,目标始终没变:中文适合长篇阅读、英文和代码清晰、国内访问稳定、体积可控。起点是通过 Google Fonts CDN 加载 Noto Serif SC,很快撞上两个问题——国内访问不稳定,且构建依赖外部服务。后面两个月的反复,都是在解这两条。