从零搭建一个 Astro 博客站:完整实战记录

实战篇 · 第 1 篇 30 分钟 需编程基础

背景

2026 年 3 月,我决定把自己用 Claude Code 的经验整理成一个教程站。选型上考虑了 Next.js、Hugo 和 Astro,最后选了 Astro——原因很简单:纯静态、构建快、对 Markdown 内容支持好,而且我之前没用过,正好拿来当实战素材。

这篇文章完整记录了我用 Claude Code 从零搭建这个站的过程。不是事后美化的”最佳实践”,而是当时实际的操作流程,包括走的弯路和浪费的时间。

第一阶段:项目初始化(对话 1-3)

对话 1:创建项目骨架

$ claude "用 Astro 创建一个新项目,要求:
   - TypeScript
   - 不用任何 UI 框架(纯 Astro 组件)
   - 内容用 Markdown,放在 content 目录
   - 需要 RSS 和 sitemap 支持
   项目名叫 claude-code-mastery"

Claude Code 用 npm create astro@latest 初始化了项目,然后装了 @astrojs/rss@astrojs/sitemap。到这一步没什么问题,标准操作。

但它做了一件我没要求的事:创建了一个 React 集成。我在 prompt 里明确说了”不用任何 UI 框架”,但它可能觉得”反正加上也不碍事”。我让它删掉了。

教训:即使 prompt 写得很明确,还是要检查它有没有”多做”。这和思维篇第 1 篇讲的一样——AI 有时候会按自己的理解”优化”你的需求。

对话 2:内容模型设计

$ claude "设计 content collection 的 schema:
   字段:title, module(枚举 m1-basics/m2-thinking/m3-practice/m4-advanced),
   order(数字), description, duration, level, publishedAt, draft
   在 src/content.config.ts 里配置"

这步很顺利,一次过。Schema 设计这种结构化的任务是 Claude Code 的强项——规则明确,没有模糊空间。

对话 3:目录结构调整

创建完之后我发现 Astro 的 content collection 默认把 Markdown 文件放在 src/content/ 里,但我想放在项目根目录的 content/ 下面。这个调整花了两轮对话才搞定,因为涉及修改 content.config.ts 里的 loader 配置。

第一轮 Claude Code 给了一个用 file() loader 的方案,实际运行报错。第二轮我把报错信息贴给它,它改用了 glob() loader,这次成功了。

// 最终方案
const lessons = defineCollection({
  loader: glob({ pattern: '**/*.md', base: './content' }),
  schema: z.object({ /* ... */ }),
});

时间消耗:约 25 分钟,其中 10 分钟在排查 loader 的问题。

第二阶段:页面开发(对话 4-15)

这是最花时间的阶段,一共开了 12 次对话。

布局系统(对话 4-6)

我先让它创建三个布局:BaseLayout(全局)、LessonLayout(教程页)、PageLayout(静态页)。

这里犯了一个错误:我在第 4 次对话里把三个布局一口气都描述了。结果 Claude Code 产出了三个布局文件,但它们之间的嵌套关系搞混了——LessonLayout 没有正确继承 BaseLayout 的 head 标签。

怎么修的:没有在那次对话里继续修,而是开了新对话,一次只处理一个布局。先把 BaseLayout 彻底搞对(对话 5),再基于它写 LessonLayout(对话 6)。这正是小步快跑的实际应用。

首页设计(对话 7-10)

首页是我和 Claude Code 协作最纠结的部分。

对话 7:我先描述了我想要的大致结构——hero 区、数据统计、课程卡片、理念介绍、最新文章、底部 CTA。Claude Code 一次性生成了整个页面,大约 200 行 Astro 代码。

问题来了:代码能跑,但设计太”模板”了。 看起来就像从某个 landing page 模板复制过来的——完美的对称布局、标准的 CTA 按钮、刻板的分区。能用,但没有任何辨识度。

对话 8-9:我花了两次对话调整设计细节。把颜色方案从蓝灰色改成暖色调(米白底 + 砖红强调色),调整字体组合,重写了文案。这些事情不能交给 AI——设计品味和文案调性是需要人来把控的。

对话 10:加了终端组件。我让 Claude Code 写一个仿终端的展示组件,放在 hero 区右侧。这个它做得很好,CSS 动画、语法高亮色都不用我多说。技术性强、创意性弱的任务,是它的舒适区。

教程页和侧边栏(对话 11-15)

教程页需要一个侧边栏导航,显示当前模块的所有文章。这个需求说起来简单,实际做的时候碰到两个问题:

  1. 路由设计:我想用 /m1/01-what-is-claude-code 这种短路径,但 Astro 的 content collection 默认 slug 是 m1-basics/01-what-is-claude-code。需要手动做路径映射。

  2. 分页组件:上一篇/下一篇的逻辑需要知道当前模块的所有文章顺序。Claude Code 第一版的排序用的是字母序而不是 order 字段,导致第 10 篇排在第 2 篇前面。

这两个问题各花了一次对话解决。不难,但如果不是分步做、每步验证,这种小问题会叠加起来变得很难排查。

第三阶段:样式打磨(对话 16-25)

CSS 是我和 Claude Code 合作效率最低的环节。不是因为它写不好 CSS——它写的 CSS 语法上完全没问题——而是因为视觉效果只有你自己看了才知道对不对

典型的流程是:

  1. 我描述一个视觉效果
  2. Claude Code 写出 CSS
  3. 我在浏览器里看效果
  4. 不满意,重新描述
  5. 循环 3-4 次

比如调整卡片悬浮效果那次,我描述”鼠标悬浮时卡片微微上浮,顶部出现一条强调色的线”。Claude Code 写了代码,效果是对的,但线太粗了、动画太快了。我又说”线从 3px 改成 2px,过渡时间从 0.2s 改成 0.3s”。来回调了 4 轮。

后来我学到的方法:CSS 微调这种事,直接在浏览器 DevTools 里试好数值,然后告诉 Claude Code 具体参数。不要让它猜你想要什么效果——它猜不准。

第四阶段:内容和 SEO(对话 26-33)

SEO 组件(对话 26-27)

让 Claude Code 写了一个 SEOHead 组件,包含 Open Graph、Twitter Card 和 JSON-LD 结构化数据。这类有明确规范的任务它做得非常好——schema.org 的格式、meta 标签的属性,它比我记得清楚。

唯一改了一次:它在 JSON-LD 里把 publisher 写成了个人(Person),但对于一个教程站应该用 Organization。小问题,一次对话修复。

RSS 和 Sitemap(对话 28)

这两个功能基本是标准实现,Claude Code 一次搞定。Astro 的官方集成已经很成熟了,没有踩坑的空间。

响应式适配(对话 29-33)

移动端适配又花了 5 次对话。最大的问题是导航——桌面端的水平导航在移动端要变成汉堡菜单。Claude Code 写了一个纯 CSS + JS 的方案,功能正确但动画生硬。我又花了 2 次对话调整过渡效果。

侧边栏在移动端的处理也费了一些功夫。最终方案是移动端把侧边栏从固定定位改成正常文档流,放在文章上面。

最终数据

完成整个项目花了大约 3 天,对话轮次分布:

阶段对话次数占比一次成功率
项目初始化38%67%
页面开发1232%50%
样式打磨1027%30%
内容和 SEO822%75%
修复和调整411%-
合计37100%约 50%

几个数字值得注意:

  • 一次成功率约 50%:平均每两次对话就有一次需要修正
  • 样式相关的成功率最低(30%):视觉类任务最难用文字精确描述
  • 结构化任务成功率最高(75%):schema、SEO、RSS 这类有规范可循的任务

如果重来一次

回头看这个过程,有几件事我会做不同:

  1. 先画线框再写代码——首页设计浪费了太多时间在”来回调”上。如果先用 Figma 或者纸笔画好大致布局,再让 Claude Code 实现,效率会高很多。

  2. CSS 微调不要用对话——直接在 DevTools 里调好数值,然后告诉它改成什么。用自然语言描述视觉效果,效率极低。

  3. 不要在一次对话里塞太多文件——第 4 次对话(三个布局一起做)就是反面教材。文件之间有依赖关系时,必须分开处理。

  4. CLAUDE.md 应该第一天就写——我到第二天才补上。如果一开始就写好项目约定(色彩方案、命名规范、目录结构),很多返工都可以避免。

觉得有用?关注公众号获取更多

每周更新 Claude Code 实战技巧、工具对比、行业动态。回复「模板」获取 CLAUDE.md 模板合集。

微信扫码关注 CC精通之路