用 Claude Code 开发 Astro 内容站:Content Collections、SSG 与验证流程
用 Claude Code 构建 Astro 内容站,覆盖配置、文章列表、标签页、局部水合和构建检查。
为什么 Claude Code 适合 Astro
Astro 很适合博客、文档站、作品集、产品落地页这类以阅读为主的网站。它可以使用 React、Vue、Svelte 等组件,但不会默认把整站都变成一个大型客户端应用。所谓 island architecture,中文可以理解为“岛屿架构”:静态内容保持静态,只有搜索框、筛选器、购买按钮等真正需要交互的部分才在浏览器中加载 JavaScript。
Claude Code 在 Astro 项目里最有价值的地方,不是一次性生成很多文件,而是先读懂项目结构,再做小范围修改。Astro 的结果由 astro.config.mjs、src/content.config.ts、src/pages/、src/components/、图片、路由和构建命令共同决定。让 Claude Code 先说明计划,可以减少不必要的 CMS、状态管理库或大范围重构。
本文采用当前 Astro Content Collections 的写法,包括 src/content.config.ts、astro/loaders 和 astro/zod。实际操作前建议同时查看官方资料:Claude Code Quickstart、Astro Content Collections、Astro template directives 和 Astro routing reference。站内也可以配合阅读 SSR/SSG 对比 与 SEO 优化。
先把项目范围说清楚
不要只对 Claude Code 说“帮我做一个 Astro 博客”。这类提示太宽,容易让它同时改设计、路由、内容模型和依赖。更稳妥的做法是说明:这是静态内容站,需要 MDX、sitemap、类型化 frontmatter、文章列表、标签页和构建验证。
npm create astro@latest my-astro-site
cd my-astro-site
npx astro add mdx sitemap tailwind
npm run dev
项目建好后,可以这样让 Claude Code 先检查:
claude "把这个 Astro 项目当作内容站审查。读取 astro.config.mjs、src/content.config.ts、src/pages、src/components。先说明实现计划和验证命令,再开始编辑。"
基础配置保持简单即可:
// astro.config.mjs
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
import sitemap from '@astrojs/sitemap';
import tailwind from '@astrojs/tailwind';
export default defineConfig({
site: 'https://example.com',
output: 'static',
integrations: [mdx(), sitemap(), tailwind()],
markdown: {
shikiConfig: {
theme: 'github-dark',
},
},
});
发布前一定要把 site 改成正式域名。sitemap、canonical URL 和社交分享链接都依赖它,保留示例域名会影响 SEO 质量。
用当前方式定义 Content Collections
Content Collections 可以把 Markdown 或 MDX 文章当成有类型的数据来管理。也就是说,标题、描述、发布日期、标签等字段不是随便写,而是会被 schema 检查。多语言站点尤其需要这一点,因为翻译时很容易误改 frontmatter。
// src/content.config.ts
import { defineCollection } from 'astro:content';
import { glob } from 'astro/loaders';
import { z } from 'astro/zod';
const blog = defineCollection({
loader: glob({
base: './src/content/blog',
pattern: '**/*.{md,mdx}',
}),
schema: z.object({
title: z.string().max(80),
description: z.string().max(120),
pubDate: z.coerce.date(),
updatedDate: z.coerce.date().optional(),
tags: z.array(z.string()).default([]),
draft: z.boolean().default(false),
heroImage: z.string().optional(),
}),
});
export const collections = { blog };
可以继续让 Claude Code 审查:
claude "检查 src/content.config.ts 是否符合 Astro 5 的 Content Collections 写法。确认 description 长度、draft 排除、updatedDate 可选字段和旧 API 混用问题。"
这样做的收益很实际:description 太长、日期格式错误、tags 不是数组、图片字段缺失,都可以在开发阶段发现,而不是上线后才发现页面坏了。
实例一:文章列表与分页
文章列表是内容站最常见的页面。重点是不要相信 getCollection() 返回的默认顺序,需要自己按发布时间排序,并排除草稿。
---
// src/pages/blog/[...page].astro
import { getCollection } from 'astro:content';
import PostCard from '../../components/PostCard.astro';
export async function getStaticPaths({ paginate }) {
const posts = (await getCollection('blog', ({ data }) => data.draft !== true))
.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());
return paginate(posts, { pageSize: 12 });
}
const { page } = Astro.props;
---
<section class="mx-auto max-w-5xl px-4 py-10">
<h1 class="text-3xl font-bold">Blog</h1>
<div class="mt-8 grid gap-6 md:grid-cols-2">
{page.data.map((post) => <PostCard post={post} />)}
</div>
<nav class="mt-10 flex justify-between">
{page.url.prev ? <a href={page.url.prev}>Previous</a> : <span />}
{page.url.next ? <a href={page.url.next}>Next</a> : <span />}
</nav>
</section>
卡片组件负责展示日期、标题、摘要和标签:
---
// src/components/PostCard.astro
import type { CollectionEntry } from 'astro:content';
type Props = {
post: CollectionEntry<'blog'>;
lang?: string;
};
const { post, lang = 'zh' } = Astro.props;
const href = lang === 'ja' ? `/blog/${post.id}/` : `/${lang}/blog/${post.id}/`;
const date = post.data.updatedDate ?? post.data.pubDate;
---
<article class="rounded border border-slate-200 p-5">
<p class="text-sm text-slate-500">
<time datetime={date.toISOString()}>{date.toLocaleDateString('zh-CN')}</time>
</p>
<h2 class="mt-2 text-xl font-semibold">
<a href={href}>{post.data.title}</a>
</h2>
<p class="mt-3 text-slate-700">{post.data.description}</p>
<ul class="mt-4 flex flex-wrap gap-2">
{post.data.tags.map((tag) => <li class="rounded bg-slate-100 px-2 py-1 text-xs">{tag}</li>)}
</ul>
</article>
这个模式可以用于三个常见场景:个人技术博客、公司内部知识库、产品更新日志。无论是哪一种,都应该先保证内容结构稳定,再让 Claude Code 调整视觉样式。
实例二:标签页和局部水合
标签页的常见坑是直接把标签名当作 URL。中文、空格、大写字母都会带来问题。更安全的做法是把 URL slug 和展示 label 分开。
---
// src/pages/tags/[tag]/[...page].astro
import { getCollection } from 'astro:content';
import PostCard from '../../../components/PostCard.astro';
const tagSlug = (tag) =>
encodeURIComponent(tag.toLowerCase().trim().replace(/\s+/g, '-'));
export async function getStaticPaths({ paginate }) {
const posts = await getCollection('blog', ({ data }) => data.draft !== true);
const groups = new Map();
for (const post of posts) {
for (const label of post.data.tags) {
const slug = tagSlug(label);
const group = groups.get(slug) ?? { slug, label, posts: [] };
group.posts.push(post);
groups.set(slug, group);
}
}
return [...groups.values()].flatMap((group) =>
paginate(group.posts, {
params: { tag: group.slug },
props: { tag: group.label },
pageSize: 10,
}),
);
}
const { page, tag } = Astro.props;
---
<section class="mx-auto max-w-5xl px-4 py-10">
<h1 class="text-3xl font-bold">Tag: {tag}</h1>
<div class="mt-8 grid gap-6 md:grid-cols-2">
{page.data.map((post) => <PostCard post={post} />)}
</div>
</section>
第三个实例是搜索框。不要为了一个搜索框把整个页面变成客户端应用。静态部分继续使用 Astro,只有搜索框使用客户端水合。
---
// src/pages/index.astro
import Hero from '../components/Hero.astro';
import SearchBox from '../components/SearchBox.tsx';
import LatestPosts from '../components/LatestPosts.astro';
---
<Hero />
<SearchBox client:visible />
<LatestPosts />
client:load 适合首屏必须马上交互的组件,client:visible 适合进入视口后再加载的组件。让 Claude Code 在添加 directive 前说明原因,可以避免 JavaScript 过量。
失败例和检查方式
失败例一是复制旧教程。看到 src/content/config.ts 或旧 collection 选项时,要先核对当前 Astro 版本。失败例二是一次让 Claude Code 改整站,结果列表、标签、样式和 SEO 同时变化,review 很困难。失败例三是忽略 heroImage、description 和 OGP,导致社交分享效果差。失败例四是只看 build 成功,却没有检查分页、内部链接、外部链接和移动端显示。
发布前至少运行:
npm run build
npx astro check
npm run preview
构建失败时,不要只说“修复它”,而是让 Claude Code 先分类:
claude "读取 npm run build 的失败日志。按 Astro 语法、Content Collections schema、MDX code fence、路由生成、链接问题分类,然后给出最小修复方案。"
CTA 与实际验证结果
如果你只是想掌握基本命令,可以先看免费速查表。如果需要可复用模板,可以查看产品列表。如果是团队要把 Astro 内容站、审查规则和 Claude Code 工作流一起落地,可以考虑培训与导入咨询。
实际试下来,Claude Code 生成 .astro 文件很快,但需要人工重点检查四点:Astro API 是否过期、标签 URL 是否安全编码、client:load 是否用太多、构建验证是否真的跑过。最稳定的流程是:先让它读项目,再限制修改范围,然后对照官方文档检查,最后执行 build 和预览。这样比一次性要求它重做整个网站可靠得多。
免费 PDF: Claude Code 速查表
输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。
我们会妥善保护你的信息,不发送垃圾邮件。
把 Claude Code 变成真正能带来结果的工作流
先领取中文说明的免费 PDF,再进入英文商品页选择合适的教材。如果你需要团队落地、流程设计或内容变现支持,也可以直接咨询。
关于作者
Masa
专注 Claude Code 实务流程、团队导入和内容转化的工程师。
相关文章
从Obsidian到CLAUDE.md的Claude Code流程:不再反复解释上下文
把 Obsidian 工作笔记整理成 CLAUDE.md 运行说明,让 Claude Code 每次都带着正确上下文开始。
Claude Code 收入 CTA 路由:从文章分流到 PDF、Gumroad 与咨询
用 Claude Code 按读者意图把文章流量分到免费 PDF、Gumroad 教材或咨询入口。
Claude Code 团队交接规则: 把审查证据、权限、回滚和收入路径一起交付
面向团队的 Claude Code 交接格式: 证据、权限、回滚、免费 PDF、Gumroad 与咨询路径都要可审查。