Claude CodeでAstroサイトを作る実践ガイド|Content CollectionsとSSG運用
Claude CodeでAstroサイトを作る手順を、設定・記事一覧・タグページ・検証まで実装コード付きで解説。
Claude CodeとAstroは相性がいい
Astroは、ブログ、ドキュメント、ポートフォリオ、商品LPのような「読むページ」が多いサイトに向いたフレームワークです。ReactやVueのコンポーネントも使えますが、最初から全ページへJavaScriptを配るのではなく、必要な部分だけをブラウザで動かします。この考え方は「アイランドアーキテクチャ」と呼ばれます。難しく聞こえますが、要するに「静的に出せる部分は静的に出し、検索やフォームなど動きが必要な部品だけ後から動かす」設計です。
Claude CodeをAstro開発に使う価値は、単にファイルを生成させることではありません。astro.config.mjs、src/content.config.ts、src/pages/、src/components/ の関係を読ませて、「どこを直せば安全か」「ビルドで検証できるか」まで一連の作業にできる点にあります。初心者がつまずきやすいAstro独自の記法も、Claude Codeに「まず方針を説明してから編集して」と頼むと、差分を理解しながら進められます。
この記事では、Claude Codeに任せる前提で、Astro 5系のContent Collections、記事一覧、タグページ、アイランド化、ビルド検証までを実装レベルで整理します。公式情報は必ず原典で確認してください。基準にしたのはClaude Code Quickstart、Astro Content Collections、Astro template directives、Astro routing referenceです。SSGとSSRの判断はClaude Code SSR/SSG比較、検索流入を増やす設計はClaude Code SEO最適化も合わせて読むとつながります。
最初に作るプロジェクトの形
Astroは自由度が高いので、最初に「何を作るか」をClaude Codeへ具体的に伝えます。初心者ほど「いい感じのブログを作って」ではなく、ページ構成、記事データ、ビルド方式、検証コマンドを先に決めた方が失敗しません。
npm create astro@latest my-astro-site
cd my-astro-site
npx astro add mdx sitemap tailwind
npm run dev
作成後、Claude Codeには次のように頼みます。
claude "Astroのcontent siteとして構成を確認して。astro.config.mjs、src/content.config.ts、src/pages、src/componentsを読み、編集前に実装方針と検証コマンドを出して。"
この時点でClaude Codeに「いきなり編集しない」と指定するのがコツです。Astroはページファイルだけでなく、Content Collections、画像、OGP、サイトマップ、ページネーションが絡みます。編集範囲を狭くしてから実装させると、意図しないCMS導入や不要な状態管理ライブラリ追加を防げます。
astro.config.mjs は次のような最小構成から始めると扱いやすいです。
// 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 を本番URLにしておくと、sitemapやcanonical URLの生成が安定します。開発中の仮URLのまま公開すると、検索エンジン向けのURLがずれるので注意してください。
Content Collectionsを現行の書き方で定義する
Content Collectionsは、MarkdownやMDXの記事を「同じ型を持つデータ」として扱う仕組みです。frontmatterの入力漏れをビルド時に見つけられるため、記事数が増えるサイトでは早めに入れる価値があります。以前のAstro記事では src/content/config.ts の例がよく出てきますが、Astro 5系の公式ドキュメントでは src/content.config.ts と astro/loaders を使う形が基本です。
// 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として古いAPIが混ざっていないか、descriptionの文字数、draft除外、updatedDateの扱いを確認して。"
このスキーマを入れると、descriptionが長すぎる、日付が壊れている、tags が配列になっていない、といった問題をビルド前後で見つけやすくなります。特に多言語サイトでは、翻訳時にfrontmatterを壊しやすいので、Claude Codeへ「frontmatterの固定項目は変更しない」と明示してください。
記事一覧ページを作る
実例1つ目は、ブログの一覧ページです。ポイントは、getCollection() の戻り順を信用しないことです。Astro公式ドキュメントでも、順序が必要なら自分でsortする前提です。公開日の降順に並べ、下書きを除外し、共通カードに渡します。
---
// 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 = 'ja' } = 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('ja-JP')}</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へは「カードは装飾を増やす前に、日付・タイトル・説明・タグを壊さないこと」と伝えると、見た目だけの変更で情報設計が崩れにくくなります。
タグページとアイランド化を組み合わせる
実例2つ目はタグ別一覧です。タグ名をそのまま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>
実例3つ目は検索UIです。Astroページ全体をReact化する必要はありません。検索ボックスだけReactやVueで作り、client:visible や client:load を選びます。client:load は最初から操作が必要なUI、client:visible は画面に入ってからでよいUIに向いています。
---
// 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 を付けることです。Astroの強みはJavaScriptを減らせる点なので、Claude Codeには「インタラクションが必要な理由を書いてからclient directiveを選んで」と頼みます。
よくある失敗と回避策
失敗例1は、古いContent Collectionsの記事をそのままコピーすることです。src/content/config.ts と type: 'content' の古い例が残っている場合、Astro 5系の新しいプロジェクトでは公式の src/content.config.ts、glob()、astro/zod の例に合わせて確認します。既存プロジェクトのバージョンが古い場合は、まず package.json と公式ドキュメントを照合してください。
失敗例2は、Claude Codeに「全部直して」と頼むことです。Astroでは、一覧ページ、記事詳細、OGP、タグページ、サイトマップ、CSSがまとめて変わるとレビューが難しくなります。「今回はタグページだけ」「frontmatterは触らない」「最後に npm run build を実行」と範囲を狭くします。
失敗例3は、画像とOGPを後回しにすることです。記事品質ではアイキャッチ画像が必要です。heroImage のパス、alt相当の説明、OGP生成を確認しないと、SNSで共有されたときに弱いページになります。SEO改善はClaude Code SEO最適化の観点も使ってください。
失敗例4は、ビルドが通っただけで公開OKにすることです。npm run build は大事ですが、ページネーション、内部リンク、外部リンク、モバイル表示、収益導線CTAまで確認して初めて公開判断できます。記事が増えたサイトでは、毎日公開チェックリストのように確認項目を固定すると事故が減ります。
検証コマンドとClaude Codeへの頼み方
実装後は、最低限この順番で確認します。
npm run build
npx astro check
npm run preview
このサイトのように独自チェックがある場合は、ビルドスクリプトに品質チェック、ローカライズチェック、コードフェンスチェックを入れておくと安心です。Claude Codeには次のように頼むと、失敗ログから原因を切り分けやすくなります。
claude "npm run buildの失敗を読んで。Astroの構文エラー、Content Collectionsのschema違反、MDXコードフェンス、リンク切れ候補に分類して、最小差分で直して。"
重要なのは、エラーを丸めて「直して」ではなく、分類を先に出させることです。MDXのコードフェンス崩れとAstroテンプレート構文エラーは見た目が似ていても原因が違います。分類させると、記事本文だけを直すべきか、コンポーネントを直すべきか判断しやすくなります。
収益導線CTAを自然に入れる
Astro記事は技術メモで終わらせるより、読者の次の行動を用意した方が価値が出ます。初心者には無料チートシートでClaude Codeの基本コマンドを渡し、実装テンプレートが欲しい読者には商品一覧を案内します。チームでAstroサイト、社内ドキュメント、記事運用を整えたい場合はClaude Code研修・導入相談につなげるのが自然です。
押し売りにしないコツは、CTAを「この記事で解決できなかった次の課題」に合わせることです。たとえば、個人ブログならSEOとOGP、企業サイトならレビュー権限とCI、メディア運用なら多言語品質と公開チェックが次の課題になります。CTAは売り込み文ではなく、読者の作業を止めないための分岐です。
実際に試した結果
この記事では、Claude CodeにAstro構成を読ませる前提で、Content Collections、一覧ページ、タグページ、アイランド化、ビルド確認の流れに分けて整理しました。実際に試すと、Claude Codeは .astro ファイルの生成自体は速い一方で、Content Collectionsの古い書き方、タグURLのエンコード、client:load の付けすぎを見逃しやすい場面がありました。最初に公式ドキュメントの対象バージョンを指定し、編集範囲と検証コマンドを固定すると、初心者でも差分を追いやすくなります。Astro開発では「AIに全部任せる」より、「構成を読ませる、狭く直させる、ビルドで確認する」の順番が一番安定しました。
無料PDF: Claude Code はじめてのチートシート
まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。
スパムは送りません。登録情報は厳重に管理します。
Claude Codeを仕事で使える形にしませんか?
無料PDFで基礎を固めたあと、すぐ使えるテンプレート集で試し、必要なら業務自動化や導入相談まで進められます。
この記事を書いた人
Masa
Claude Codeの実務活用、導入設計、収益導線改善を検証しているエンジニア。10言語の技術メディアを運営中。
関連書籍・参考図書
この記事のテーマに関連する書籍を楽天ブックスで探せます。
※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。
関連記事
ObsidianメモをCLAUDE.mdに変えるClaude Code運用: 文脈を毎回説明しない仕組み
Obsidianの作業メモからCLAUDE.md用の運用ノートを作り、Claude Codeに安定した文脈を渡す方法。
Claude Code Revenue CTA Routing: 記事からPDF、Gumroad、相談へ送る設計
PVだけで終わらせず、読者の状態に合わせて無料PDF、Gumroad教材、導入相談へ分岐するCTA設計です。
Claude Codeチーム引き継ぎルール: レビュー、権限、収益導線まで渡す実務手順
Claude Codeの作業をチームで渡すための証拠、権限、ロールバック、無料PDF/Gumroad/相談導線の実務ルール。