返回

博客首页:Clawd 浮在发光的地平线上,中间是 VIBE CODING 大标题博客首页:Clawd 浮在发光的地平线上,中间是 VIBE CODING 大标题

起因#

我想要一个自己的博客,放 AI 编程的心得、开发日志、看到的资讯,还有各种乱七八糟的东西。要求不多:能二次开发,自己用,长得好看。

这个博客从头到尾是我和 Claude Code 在终端里一句一句聊出来的。我负责提需求、看效果、说哪里不对,写代码、调试、部署基本都交给它。这篇是第一篇文章,也是用它做好的文章接口发上来的。

选程序#

一开始对比了 Halo、Typecho、Ghost、Payload 这几个,最后选了 Astro 做的静态博客:文章就是 Markdown 文件,没有数据库,改起来最顺手,也最适合让 AI 来改。

现成的主题看了好几个都觉得一般,最后拿 Astro Pure ↗ 当底子,因为它结构干净、好改。

首页:照着一个作品集网站重写动效#

我在网上看到一个很喜欢的作品集首页(herasymenkox.com):全屏作品图上压一个超大标题,滚动时图片带着扭曲效果切换,还能切成横向的画廊视图。

人家的代码和素材不能直接拿来用,所以先让 Claude Code 把这个页面拆清楚:截图、录屏、读它的脚本,弄明白每个交互怎么回事,再用 Three.js 和 GSAP 自己重写一遍:

  • 滑块视图:滚轮推着画面走,下一张带着噪声边缘擦出来,停手后吸附到最近一张
  • 画廊视图:卡片横向循环,拖得越快弯得越厉害
  • 点一下:图片飞到详情页的封面位置,详情里列出这个分类的文章

首页的画廊视图,拖动时卡片会弯成弧线

第一版其实做错了。我说"点击一下才会往下走",它一开始做成了滚轮翻页,后来回去仔细读了原站的源码、逐帧截图才改对。让 AI 照着参考做东西,得先让它把参考看完,不能只看一眼截图就开工。

首页的五张图是 Claude Code 的吉祥物 Clawd。官方没有发布过壁纸,用的是两位网友的同人作品,按各自的授权署了名,出处在图片来源页。

全站统一成一种风格#

主题原来的页面是圆角卡片,和首页的硬朗风格对不上。于是全站改成首页那一套:直角、深色、Inter Tight 加 JetBrains Mono、珊瑚橙点缀。界面全部换成中文,主题包里写死的英文用 bun patch 打了补丁。

文章按 5 个分类归档:AI 编程、开发日志、资讯、工具、随记,对应首页的五张卡片;标签另外自由填写。

写文章的三种方式#

  1. 本地后台:在自己电脑上跑开发服务器,打开 Keystatic 后台,像写文档一样写,友链也在这里维护
  2. 文章接口:带密钥调用就能发布,适合做完开发后让 AI 直接写一篇总结发上来,这篇就是这么发的
  3. 直接写 Markdown 文件,再部署

本地的 Keystatic 后台,只在开发时存在,线上没有入口

接口收到文章后会先做几道检查:字段对不对、正文能不能正常编译、封面图片打不打得开,都过了才写进文件,再通知服务器重新构建,大约半分钟后上线。

部署#

用 Astro 的 Node 适配器跑在自己的服务器上,前面是 nginx 和 Cloudflare。每次构建输出到一个新目录,构建成功才切换过去,失败了线上继续用旧版本;保留最近三个版本,随时可以回退。本地执行 bun run deploy 会同步代码和文章,一分钟左右上线。

踩过的坑#

开发时页面白屏。 页面请求依赖时拿到 504 Outdated Optimize Dep。原因是 Vite 第一次遇到某个依赖会重新打包、换掉版本号,正在加载的页面就全挂了;开着开发服务器再跑类型检查或构建,也会把它的缓存改掉。解决办法是启动时就把用到的依赖预打包好,并给开发服务器单独一个缓存目录。

删掉一张图,全站 500。 文章去掉最后一张本地图片后,Astro 开发模式下的图片引用清单不会更新,一直去找已经删掉的文件,重启也没用。文章全部删光时还有个类似的问题:清理旧缓存的逻辑被跳过,构建直接失败。这两处都给 Astro 打了补丁。

一个占位地址让网站发不出去。 写发文章指南时,我照着模板原样发了一篇,封面是 example.com 的占位图,打不开,结果服务器整个构建失败。现在改成两层保护:发文章时先检查封面,打不开直接拒收;构建时某张外链封面失效了,只去掉那一张,不影响网站。

Zod 的一个小陷阱。 本来想在校验外链封面的那个分支里返回空值,把失效封面去掉。结果 union 里一个分支返回空值时,Zod 会接着试下一个分支,失效的地址原样通过了。检查要挪到 union 外面:

// 不行:分支返回 undefined 后,union 会接着用下一个分支解析
z.union([remoteCover.transform(dropIfBroken), localCover])

// 可以:先解析,再在外层检查
z.union([remoteCover, localCover]).transform(dropIfBroken)
ts

结果#

从开始挑程序到上线,前后两天左右。来回最多的不是功能,而是对齐"我想要的样子":首页交互、配色、字体、中文化,每一处都是看了效果再改。

还没做完的:评论还接在主题作者的服务器上,打算关掉或者自建,所以这篇先不开评论;接口密钥也要换成更长的随机值。以后的开发日志都会用文章接口发到这里。

和 Claude Code 一起,从零搭起这个博客
https://lord7.dev/blog/building-this-blog
作者 Lord
发布于 2026年11月09日
版权协议 CC BY-NC-SA 4.0