Use Cases (更新: 2026/6/2)

用 Claude Code 开发 Astro 内容站:Content Collections、SSG 与验证流程

用 Claude Code 构建 Astro 内容站,覆盖配置、文章列表、标签页、局部水合和构建检查。

用 Claude Code 开发 Astro 内容站:Content Collections、SSG 与验证流程

为什么 Claude Code 适合 Astro

Astro 很适合博客、文档站、作品集、产品落地页这类以阅读为主的网站。它可以使用 React、Vue、Svelte 等组件,但不会默认把整站都变成一个大型客户端应用。所谓 island architecture,中文可以理解为“岛屿架构”:静态内容保持静态,只有搜索框、筛选器、购买按钮等真正需要交互的部分才在浏览器中加载 JavaScript。

Claude Code 在 Astro 项目里最有价值的地方,不是一次性生成很多文件,而是先读懂项目结构,再做小范围修改。Astro 的结果由 astro.config.mjssrc/content.config.tssrc/pages/src/components/、图片、路由和构建命令共同决定。让 Claude Code 先说明计划,可以减少不必要的 CMS、状态管理库或大范围重构。

本文采用当前 Astro Content Collections 的写法,包括 src/content.config.tsastro/loadersastro/zod。实际操作前建议同时查看官方资料:Claude Code QuickstartAstro Content CollectionsAstro template directivesAstro 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 和预览。这样比一次性要求它重做整个网站可靠得多。

#Claude Code #Astro #framework #SSG #frontend
免费

免费 PDF: Claude Code 速查表

输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。

我们会妥善保护你的信息,不发送垃圾邮件。

把 Claude Code 变成真正能带来结果的工作流

先领取中文说明的免费 PDF,再进入英文商品页选择合适的教材。如果你需要团队落地、流程设计或内容变现支持,也可以直接咨询。

Masa

关于作者

Masa

专注 Claude Code 实务流程、团队导入和内容转化的工程师。