astro について
Astroは、ブログやドキュメント、ポートフォリオなどのコンテンツ中心のサイト構築を支援するWebフレームワークのスキルです。ファイルベースルーティングやコンテンツコレクションに加え、必要なコンポーネントだけをハイドレーションする方法を扱います。
主な機能
- 01ファイルベースのページルーティング
- 02型付きMarkdown・MDXコレクション
- 03コンポーネントの選択的ハイドレーション
- 04複数のUIフレームワークに対応
- 05静的出力とオプションのSSR
活用シーン
- 01ドキュメントやブログサイトの構築
- 02コンテンツ中心のマーケティングページ作成
- 03静的ページへの選択的なインタラクション追加
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ sickn33/ agentic-awesome-skills --skill astroインストール後、Claude Code で/astroを入力して読み込まれたか確認します。
詳細
Astro Web Framework
概要
Astro は、ブログ、ドキュメント、ポートフォリオ、マーケティングサイト、eコマースなど、コンテンツが豊富なウェブサイト向けに設計されたウェブフレームワークです。中核となる革新は Islands Architecture です。デフォルトでは、Astro はブラウザーに JavaScript を一切送信しません。インタラクティブなコンポーネントは、独立した「アイランド」として選択的にハイドレーションされます。Astro は React、Vue、Svelte、Solid などの UI フレームワークを同じプロジェクト内で同時にサポートしているため、コンポーネントごとに適切なツールを選べます。
このスキルを使用する場面
- ブログ、ドキュメントサイト、マーケティングページ、ポートフォリオを構築する場合
- パフォーマンスと Core Web Vitals を最優先する場合
- Markdown または MDX ファイルを多く含むコンテンツ主体のプロジェクトの場合
- 必要に応じて動的ルートに SSR を使用しながら、SSG(静的)出力を行いたい場合
- ユーザーから
.astroファイル、Astro.props、コンテンツコレクション、client:ディレクティブについて質問された場合
仕組み
ステップ 1:プロジェクトのセットアップ
npm create astro@latest my-site
cd my-site
npm install
npm run dev
必要に応じてインテグレーションを追加します。
npx astro add tailwind # Tailwind CSS
npx astro add react # React component support
npx astro add mdx # MDX support
npx astro add sitemap # Auto sitemap.xml
npx astro add vercel # Vercel SSR adapter
プロジェクト構成:
src/
pages/ ← File-based routing (.astro, .md, .mdx)
layouts/ ← Reusable page shells
components/ ← UI components (.astro, .tsx, .vue, etc.)
content/ ← Type-safe content collections (Markdown/MDX)
styles/ ← Global CSS
public/ ← Static assets (copied as-is)
astro.config.mjs ← Framework config
ステップ 2:Astro コンポーネントの構文
.astro ファイルには、先頭にコードフェンス(サーバー専用)があり、その下にテンプレートがあります。
---
// src/components/Card.astro
// This block runs on the server ONLY — never in the browser
interface Props {
title: string;
href: string;
description: string;
}
const { title, href, description } = Astro.props;
---
<article class="card">
<h2><a href={href}>{title}</a></h2>
<p>{description}</p>
</article>
<style>
/* Scoped to this component automatically */
.card { border: 1px solid #eee; padding: 1rem; }
</style>
ステップ 3:ファイルベースのページとルーティング
src/pages/index.astro → /
src/pages/about.astro → /about
src/pages/blog/[slug].astro → /blog/:slug (dynamic)
src/pages/blog/[...path].astro → /blog/* (catch-all)
getStaticPaths を使った動的ルート:
---
// src/pages/blog/[slug].astro
export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map(post => ({
params: { slug: post.slug },
props: { post },
}));
}
const { post } = Astro.props;
const { Content } = await post.render();
---
<h1>{post.data.title}</h1>
<Content />
ステップ 3~4 と RSS のコレクション例では、Astro 5 より前の従来のコンテンツ API(src/content/config.ts、post.slug、post.render())を使用しています。新しいプロジェクトで変更せずにそのまま使用しないでください。インストールされているメジャーバージョンに応じて API を選択し、必要に応じてコンテンツローダーと render() に移行し、動的ページで getCollection をインポートしてください。Tailwind のインテグレーション設定もメジャーバージョンによって異なります。Astro 5 の移行ガイドを参照してください。
ステップ 4:コンテンツコレクション
コンテンツコレクションを使うと、Markdown ファイルと MDX ファイルに型安全にアクセスできます。
// src/content/config.ts
import { z, defineCollection } from 'astro:content';
const blog = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
date: z.coerce.date(),
tags: z.array(z.string()).default([]),
draft: z.boolean().default(false),
}),
});
export const collections = { blog };
---
// src/pages/blog/index.astro
import { getCollection } from 'astro:content';
const posts = (await getCollection('blog'))
.filter(p => !p.data.draft)
.sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf());
---
<ul>
{posts.map(post => (
<li>
<a href={`/blog/${post.slug}`}>{post.data.title}</a>
<time>{post.data.date.toLocaleDateString()}</time>
</li>
))}
</ul>
ステップ 5:アイランド — 選択的ハイドレーション
デフォルトでは、UI フレームワークのコンポーネントは JS を使わない静的 HTML としてレンダリングされます。client: ディレクティブを使ってハイドレーションします。
---
import Counter from '../components/Counter.tsx'; // React component
import VideoPlayer from '../components/VideoPlayer.svelte';
---
<Counter initialCount={0} />
<Counter initialCount={0} client:load />
<VideoPlayer src="/demo.mp4" client:visible />
<Analytics client:idle />
<MobileMenu client:media="(max-width: 768px)" />
ステップ 6:レイアウト
---
// src/layouts/BaseLayout.astro
interface Props {
title: string;
description?: string;
}
const { title, description = 'My Astro Site' } = Astro.props;
---
<html lang="en">
<head>
<meta charset="utf-8" />
<title>{title}</title>
<meta name="description" content={description} />
</head>
<body>
<nav>...</nav>
<main>
<slot />
</main>
<footer>...</footer>
</body>
</html>
---
// src/pages/about.astro
import BaseLayout from '../layouts/BaseLayout.astro';
---
<BaseLayout title="About Us">
<h1>About Us</h1>
<p>Welcome to our company...</p>
</BaseLayout>
ステップ 7:SSR モード(オンデマンドレンダリング)
アダプターを設定して、動的ページで SSR を有効にします。
// astro.config.mjs
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel';
export default defineConfig({
output: 'static', // Astro 5+: prerender by default, opt routes out below
adapter: vercel(),
});
個々のページで export const prerender = false を指定して、SSR を有効にします。
例
例 1:RSS フィード付きブログ
// src/pages/rss.xml.ts
import rss from '@astrojs/rss';
import { getCollection } from 'astro:content';
export async function GET(context) {
const posts = await getCollection('blog');
return rss({
title: 'My Blog',
description: 'Latest posts',
site: context.site,
items: posts.map(post => ({
title: post.data.title,
pubDate: post.data.date,
link: `/blog/${post.slug}/`,
})),
});
}
購読ハンドラーは、未完成のアプリケーション例です。公開する前に、addToNewsletter を定義し、静的モードではこのルートをプリレンダリング対象から外し、JSON とメールアドレスの入力をサイズ制限して検証し、下流のエラーを処理してください。また、デプロイ環境に応じた同意取得、不正利用防止、CSRF 対策を追加してください。
例 2:API エンドポイント(SSR)
// src/pages/api/subscribe.ts
import type { APIRoute } from 'astro';
export const POST: APIRoute = async ({ request }) => {
const { email } = await request.json();
if (!email) {
return new Response(JSON.stringify({ error: 'Email required' }), {
status: 400,
headers: { 'Content-Type': 'application/json' },
});
}
await addToNewsletter(email);
return new Response(JSON.stringify({ success: true }), { status: 200 });
};
例 3:アイランドとしての React コンポーネント
// src/components/SearchBox.tsx
import { useState } from 'react';
export default function SearchBox() {
const [query, setQuery] = useState('');
const [results, setResults] = useState<Array<{ id: string; title: string }>>([]);
async function search(e: React.FormEvent) {
e.preventDefault();
const data = await fetch(`/api/search?q=${encodeURIComponent(query)}`).then(r => {
if (!r.ok) throw new Error(`Search failed: ${r.status}`);
return r.json();
});
setResults(data);
}
return (
<form onSubmit={search}>
<input value={query} onChange={e => setQuery(e.target.value)} />
<button type="submit">Search</button>
<ul>{results.map(r => <li key={r.id}>{r.title}</li>)}</ul>
</form>
);
}
---
import SearchBox from '../components/SearchBox.tsx';
---
<SearchBox client:load />
ベストプラクティス
- ✅ ほとんどのコンポーネントは静的な
.astroファイルにし、インタラクティブにする必要があるものだけをハイドレーションします - ✅ すべての Markdown/MDX コンテンツにコンテンツコレクションを使用します。型安全性と自動検証が得られます
- ✅ 初期 JS を減らすため、ファーストビューより下にあるコンポーネントには
client:loadよりclient:visibleを優先します - ✅ 環境変数には
import.meta.envを使い、公開する変数にはPUBLIC_を付けます - ✅
astro:transitionsの<ClientRouter />を追加すると、SPA 全体に移行せずにスムーズなページ遷移を実現できます - ❌ すべてのコンポーネントに
client:loadを使用しないでください。Astro のパフォーマンス上の利点が損なわれます - ❌ クライアントに表示されるテンプレートで使用する
.astroのフロントマターに、秘密情報を記述しないでください - ❌ 静的モードの動的ルートで
getStaticPathsを省略しないでください。ビルドが失敗します
セキュリティと安全性に関する注意事項
- フロントマターはビルド時またはサーバー上で実行されますが、HTML、props、スクリプトに埋め込まれた値はブラウザーに公開されます。レンダリング結果に秘密情報を含めないでください。
import.meta.env.PUBLIC_*は機密性のない値にのみ使用してください。プライベートな環境変数はクライアントモジュールに自動的に公開されませんが、その値をレンダリング結果に埋め込むと漏えいします。- SSR モードを使用する場合は、データベースクエリや API 呼び出しの前に、すべての
Astro.requestの入力を検証してください。 - ユーザーが指定したコンテンツを
set:htmlでレンダリングする前に、必ずサニタイズしてください。set:htmlは自動エスケープを回避します。
よくある落とし穴
-
問題: React/Vue コンポーネントの JavaScript がブラウザーで実行されない 解決策:
client:ディレクティブ(client:load、client:visibleなど)を追加してください。指定しない場合、コンポーネントは静的な HTML としてのみレンダリングされます。 -
問題: 開発中にコンテンツを更新しても、
getStaticPathsのデータが古いままになる 解決策: Astro の開発サーバーはコンテンツファイルを監視します。content/config.tsの変更が反映されない場合は、再起動してください。 -
問題:
Astro.propsの型がanyで、入力補完が表示されない 解決策: フロントマターでPropsインターフェースまたは型を定義すると、Astro が自動的に型を推論します。 -
問題:
.astroコンポーネントの CSS がほかのコンポーネントに漏れ出す 解決策:.astroの<style>タグ内のスタイルは自動的にスコープ化されます。子要素を意図的に対象にする場合にのみ、:global()を使用してください。
関連スキル
@sveltekit— Astro のコンテンツ重視の設計ではなく、リアクティブな UI を備えたフルスタックフレームワークが必要な場合@nextjs-app-router-patterns— React を中心としたフルスタックフレームワークが必要な場合@tailwind-patterns— Tailwind CSS を使用した Astro サイトのスタイリング@progressive-web-app— Astro サイトへの PWA 機能の追加
制限事項
- このスキルは、タスクが上記の範囲に明確に当てはまる場合にのみ使用してください。
- 出力を、環境固有の検証、テスト、専門家によるレビューの代わりとして扱わないでください。
- 必要な入力、権限、安全上の境界、成功基準が不足している場合は、作業を中断して確認を求めてください。