博客又换了一次。
说”又”,是因为这已经不知道是第几次折腾了。从最早的 boblog,到 sablog,到 wordpress,再到 typecho,每次换的时候都信誓旦旦说”这次就不动了”,结果每次都没撑过几年。不过这次,倒不是对 Typecho 有什么不满——它用了好几年,一直挺稳定的。主要是最近在折腾服务器部署,顺手看了下 Astro 这个框架,发现这东西挺适合我这种写 Markdown 的人,一冲动就给换了。
为什么要换
Typecho 是个好东西,轻量、简洁,PHP 写的,部署也方便。但用久了以后,有几个一直让我有点别扭的地方:
- 依赖 PHP 和数据库。服务器上得跑 PHP-FPM + MySQL,虽然不多,但总归是个负担。我的 Debian 服务器上跑着 Docker、Nginx、各种东西,能少一个服务就少一个。
- 迁移历史太乱。从 boblog 时代留下来的老文章,格式乱七八糟的,图片链接失效、附件找不到,之前在 2016 年的时候就放弃过一次旧数据,这次又看到了那些”惨不忍睹”的东西。
- 静态化的诱惑。Astro 直接生成纯静态 HTML,往 Nginx 一丢就行,不用数据库、不用 PHP,构建完就是一堆 html/css/js,访问速度天然就快。
说白了就是:一个折腾技术的人,看到了一个新玩具,忍不住了。
工具选型
这次的开发方式和以前不太一样。以前写博客模板,基本都是自己从零撸,一个 div 一个 div 地调。这次我用了 Claude Code + DeepSeek 来辅助开发。
具体来说,就是用 Claude Code 作为编码代理,后端模型接的 DeepSeek。我先把需求大致描述了一下——要支持中英文双语、深色模式、全文搜索、标签系统、文章隐藏、SEO 优化、响应式布局——然后让它帮我把整体架构搭出来。
说实话,效果超出了预期。
技术细节
整体架构
最终的技术栈非常干净:
| 类别 | 技术 |
|---|---|
| 框架 | Astro v6.3.8 |
| 语言 | TypeScript |
| 样式 | CSS Custom Properties (Design Tokens) |
| 内容 | Markdown (Astro Content Collections + Zod 校验) |
| 搜索 | 构建时生成 JSON 索引,客户端实时搜索 |
| RSS | @astrojs/rss |
| Sitemap | @astrojs/sitemap |
| PWA | @vite-pwa/astro |
| 部署 | 静态 HTML → Vercel |
总共就三个运行时依赖:astro、@astrojs/rss、@astrojs/sitemap,开发依赖加一个 @vite-pwa/astro。npm 包少得可怜,但功能一个不少。
代码量
整个模板的代码量控制得还行:
- 组件和页面:66 个文件
- 代码总行数:约 2700 行(不含文章内容)
- 文章数量:43 篇(从 Typecho 全部迁移过来)
- 设计系统:shared.css 约 600 行,包含完整的 Design Tokens、深色模式、响应式断点、打印样式
主要模块的行数分布:
src/styles/shared.css 611 行 ← 设计系统
src/layouts/BaseLayout.astro 332 行 ← 全局布局
src/pages/search.astro 318 行 ← 搜索页
src/pages/posts/[slug].astro 263 行 ← 文章详情
src/i18n.ts 95 行 ← 中英文翻译
src/config.ts 26 行 ← 站点配置
设计风格
设计上用了 Swiss Modernism 2.0 的思路,说人话就是:简洁、克制、内容为主。
- 4pt 栅格间距系统
- 字体:Inter(拉丁文)+ Noto Sans SC(中文)+ JetBrains Mono(代码)
- 最大内容宽度 720px(文章),1080px(整体布局)
- 深色模式通过
data-theme属性切换,自动检测系统偏好 - 移动端断点:768px(平板)、480px(手机)
功能清单
这些功能是 Claude Code 一次性帮我搭出来的:
- 中英文双语 — 客户端 i18n,通过
data-i18n属性 + 内联 JS 实现,不依赖任何 i18n 框架 - 深色模式 — 手动切换 +
prefers-color-scheme自动检测,偏好存localStorage - 全文搜索 — 构建时生成 JSON 索引,客户端实时过滤,搜索标题、标签、摘要
- 文章隐藏 — frontmatter 设置
hidden: true,文章仍然可以通过 URL 访问,但不出现在任何列表中 - SEO 优化 — Open Graph、Twitter Cards、JSON-LD、Sitemap、RSS、Canonical URL,该有的都有
- 目录导航 — 文章内自动生成 TOC,滚动高亮跟随
- PWA 支持 — Service Worker 自动更新,支持离线访问,字体走 CacheFirst 策略
- 响应式布局 — 移动端自适应,侧边栏自动隐藏,触摸目标最小 44px
- 无障碍 — skip link、focus-visible、reduced motion、aria 标签
迁移过程
文章迁移其实是最费劲的部分。Typecho 的文章存在 MySQL 里,需要导出为 Markdown。好在之前写文章的时候就用的 Markdown 编辑器,所以格式基本没太大问题,主要是 frontmatter 需要统一处理一下。
每篇文章的格式统一为:
---
title: "文章标题"
date: 2025-05-27
slug: "custom-slug"
tags: ["标签1", "标签2"]
excerpt: "文章摘要"
hidden: false
---
43 篇文章,从 2006 年到 2024 年,跨越了将近 20 年。最早的一篇是 2006 年写的《谨以此文献给我永远的兄弟》,那时候还在上学。看着这些老文章,有种翻旧相册的感觉。
开发过程
从 5 月 28 号开始,到 5 月 30 号基本完成,中间的 commit 记录:
5a9964c 2026-05-30 [feat] 增加pwa支持
e196f5a 2026-05-30 [update] 更新网站图标资源
dc27b84 2026-05-30 [feat] 增加网站统计代码
1a34fd1 2026-05-30 [add] claude文件
0c1e69d 2026-05-30 [fix] 修复文章页内代码不会自动换行的问题
23e1699 2026-05-30 [fix] 修复文字过长时换行的问题等
0601a4f 2026-05-29 [fix] 修复google字体引用地址
2d9b07a 2026-05-29 [fix] 修复相关文章内容段落及属性
1cc19fa 2026-05-28 Complete blog rewrite with Astro
6522963 2026-05-28 Initial commit from Astro
整体流程就是:Claude Code 搭架构 → 写功能 → 发现问题 → 修 bug → 加特性 → 完成。中间遇到的问题主要是 Google 字体加载(国内访问不了 Google,换成了 loli.net 的镜像)、移动端文字溢出、代码块不换行之类的细节。这些让 Claude Code 自己修就行了,基本不需要我手动改代码。
一些感受
这是第一次用 AI 辅助的方式从零搭一个完整的项目。说实话,以前对这类工具是有点怀疑的——总觉得写代码这个事情,还是得自己一行一行敲才踏实。但这次体验下来,确实省了不少时间。特别是那些”体力活”——响应式布局的断点处理、CSS 变量的定义、i18n 的模板替换、SEO 的 meta 标签——这些东西技术含量不高,但写起来繁琐,让 AI 来做正合适。
不过也有一些需要手动调整的地方。比如字体加载的策略、PWA 的缓存配置、移动端的一些细节,都需要根据实际情况微调。AI 生成的东西,大概能到 80% 的完成度,剩下 20% 还是得自己来。
博客这个东西,从 2006 年开始写,到现在正好 20 年了。中间换了无数次技术栈,但写东西的习惯一直没变。不追求流量,不追求排名,就是给自己留一份记录。等到什么时候回过头来看看,还能想起某年自己做过了什么,就够了。
就像 2016 年写的那篇一样——“重新开始”。这次,算是又重新开始了一次吧。
部署在 Vercel 上,速度应该会比之前快不少。如果你发现了什么 bug,欢迎邮件告诉我。
总结
对了,这篇文章也是 DeepSeek 生成的,😊