jpskill.com
💬 コミュニケーション コミュニティ 🟢 非エンジニアでもOK 👤 管理職・人事・カスタマー対応

💬 Astro

astro

Astroは、デフォルトでJavaScriptを最小限に抑え、複数のフレームワークに対応し、コンテンツに特化したウェブサイトを構築するSkill。

⏱ クレーム返信ドラフト 15分 → 2分

📺 まず動画で見る(YouTube)

▶ 【最新版】Claude(クロード)完全解説!20以上の便利機能をこの動画1本で全て解説 ↗

※ jpskill.com 編集部が参考用に選んだ動画です。動画の内容と Skill の挙動は厳密には一致しないことがあります。

📜 元の英語説明(参考)

Build content-focused websites with Astro — zero JS by default, islands architecture, multi-framework components, and Markdown/MDX support.

🇯🇵 日本人クリエイター向け解説

一言でいうと

Astroは、デフォルトでJavaScriptを最小限に抑え、複数のフレームワークに対応し、コンテンツに特化したウェブサイトを構築するSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o astro.zip https://jpskill.com/download/2411.zip && unzip -o astro.zip && rm astro.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/2411.zip -OutFile "$d\astro.zip"; Expand-Archive "$d\astro.zip" -DestinationPath $d -Force; ri "$d\astro.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して astro.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → astro フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-17
取得日時
2026-05-17
同梱ファイル
1

💬 こう話しかけるだけ — サンプルプロンプト

  • Astro で、お客様への返信文を作って
  • Astro を使って、社内向けアナウンスを書いて
  • Astro で、メールテンプレートを整備して

これをClaude Code に貼るだけで、このSkillが自動発動します。

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

Astro Web フレームワーク

概要

Astro は、コンテンツが豊富なウェブサイト(ブログ、ドキュメント、ポートフォリオ、マーケティングサイト、Eコマースなど)向けに設計されたウェブフレームワークです。その核となる革新は、アイランドアーキテクチャです。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/          ← ファイルベースのルーティング (.astro, .md, .mdx)
  layouts/        ← 再利用可能なページシェル
  components/     ← UI コンポーネント (.astro, .tsx, .vue など)
  content/        ← 型安全なコンテンツコレクション (Markdown/MDX)
  styles/         ← グローバル CSS
public/           ← 静的アセット (そのままコピーされます)
astro.config.mjs  ← フレームワーク設定

ステップ 2: Astro コンポーネント構文

.astro ファイルは、上部にコードフェンス (サーバーのみ) と、その下にテンプレートがあります。

---
// src/components/Card.astro
// このブロックはサーバーのみで実行されます — ブラウザでは決して実行されません
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>
  /* このコンポーネントに自動的にスコープされます */
  .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 (動的)
src/pages/blog/[...path].astro → /blog/* (キャッチオール)

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 />

ステップ 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 フレームワークコンポーネントは JavaScript なしで静的 HTML にレンダリングされます。ハイドレーションには client: ディレクティブを使用します。

---
import Counter from '../components/Counter.tsx';  // React コンポーネント
import VideoPlayer from '../components/VideoPlayer.svelte';
---

<!-- 静的 HTML — ブラウザに JavaScript は送信されません -->
<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/serverless';

export default defineConfig({
  output: 'hybrid',  // 'static' | 'server' | 'hybrid'
  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,
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

Astro Web Framework

Overview

Astro is a web framework designed for content-rich websites — blogs, docs, portfolios, marketing sites, and e-commerce. Its core innovation is the Islands Architecture: by default, Astro ships zero JavaScript to the browser. Interactive components are selectively hydrated as isolated "islands." Astro supports React, Vue, Svelte, Solid, and other UI frameworks simultaneously in the same project, letting you pick the right tool per component.

When to Use This Skill

  • Use when building a blog, documentation site, marketing page, or portfolio
  • Use when performance and Core Web Vitals are the top priority
  • Use when the project is content-heavy with Markdown or MDX files
  • Use when you want SSG (static) output with optional SSR for dynamic routes
  • Use when the user asks about .astro files, Astro.props, content collections, or client: directives

How It Works

Step 1: Project Setup

npm create astro@latest my-site
cd my-site
npm install
npm run dev

Add integrations as needed:

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

Project structure:

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

Step 2: Astro Component Syntax

.astro files have a code fence at the top (server-only) and a template below:

---
// 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>

Step 3: File-Based Pages and Routing

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)

Dynamic route with 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 />

Step 4: Content Collections

Content collections give you type-safe access to Markdown and MDX files:

// 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>

Step 5: Islands — Selective Hydration

By default, UI framework components render to static HTML with no JS. Use client: directives to hydrate:

---
import Counter from '../components/Counter.tsx';  // React component
import VideoPlayer from '../components/VideoPlayer.svelte';
---

<!-- Static HTML — no JavaScript sent to browser -->
<Counter initialCount={0} />

<!-- Hydrate immediately on page load -->
<Counter initialCount={0} client:load />

<!-- Hydrate when the component scrolls into view -->
<VideoPlayer src="/demo.mp4" client:visible />

<!-- Hydrate only when browser is idle -->
<Analytics client:idle />

<!-- Hydrate only on a specific media query -->
<MobileMenu client:media="(max-width: 768px)" />

Step 6: Layouts

---
// 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 />  <!-- page content renders here -->
    </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>

Step 7: SSR Mode (On-Demand Rendering)

Enable SSR for dynamic pages by setting an adapter:

// astro.config.mjs
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel/serverless';

export default defineConfig({
  output: 'hybrid',  // 'static' | 'server' | 'hybrid'
  adapter: vercel(),
});

Opt individual pages into SSR with export const prerender = false.

Examples

Example 1: Blog with RSS Feed

// 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}/`,
    })),
  });
}

Example 2: API Endpoint (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 });
};

Example 3: React Component as Island

// src/components/SearchBox.tsx
import { useState } from 'react';

export default function SearchBox() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState([]);

  async function search(e: React.FormEvent) {
    e.preventDefault();
    const data = await fetch(`/api/search?q=${query}`).then(r => 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';
---
<!-- Hydrated immediately — this island is interactive -->
<SearchBox client:load />

Best Practices

  • ✅ Keep most components as static .astro files — only hydrate what must be interactive
  • ✅ Use content collections for all Markdown/MDX content — you get type safety and auto-validation
  • ✅ Prefer client:visible over client:load for below-the-fold components to reduce initial JS
  • ✅ Use import.meta.env for environment variables — prefix public vars with PUBLIC_
  • ✅ Add <ViewTransitions /> from astro:transitions for smooth page navigation without a full SPA
  • ❌ Don't use client:load on every component — this defeats Astro's performance advantage
  • ❌ Don't put secrets in .astro frontmatter that gets used in client-facing templates
  • ❌ Don't skip getStaticPaths for dynamic routes in static mode — builds will fail

Security & Safety Notes

  • Frontmatter code in .astro files runs server-side only and is never exposed to the browser.
  • Use import.meta.env.PUBLIC_* only for non-sensitive values. Private env vars (no PUBLIC_ prefix) are never sent to the client.
  • When using SSR mode, validate all Astro.request inputs before database queries or API calls.
  • Sanitize any user-supplied content before rendering with set:html — it bypasses auto-escaping.

Common Pitfalls

  • Problem: JavaScript from a React/Vue component doesn't run in the browser Solution: Add a client: directive (client:load, client:visible, etc.) — without it, components render as static HTML only.

  • Problem: getStaticPaths data is stale after content updates during dev Solution: Astro's dev server watches content files — restart if changes to content/config.ts are not reflected.

  • Problem: Astro.props type is any — no autocomplete Solution: Define a Props interface or type in the frontmatter and Astro will infer it automatically.

  • Problem: CSS from a .astro component bleeds into other components Solution: Styles in .astro <style> tags are automatically scoped. Use :global() only when intentionally targeting children.

Related Skills

  • @sveltekit — When you need a full-stack framework with reactive UI (vs Astro's content focus)
  • @nextjs-app-router-patterns — When you need a React-first full-stack framework
  • @tailwind-patterns — Styling Astro sites with Tailwind CSS
  • @progressive-web-app — Adding PWA capabilities to an Astro site

Limitations

  • Use this skill only when the task clearly matches the scope described above.
  • Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
  • Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.