Astroで個人技術ブログを始める最小構成

個人の技術ブログを始めると、最初からCMS、DB、検索、コメントまで入れたくなります。しかし、記事をMarkdownで書くだけなら、Astroの静的出力で十分なことが多いです。一覧と詳細の生成やRSSの配信も、静的ビルドへ含められます。
ここでは、Astro 7系と現行のContent Collectionsを前提に、1本の記事が「Markdown → スキーマ検証 → 動的ルート → 静的HTML」へ変わる最小経路を確認します。AstroのAPIは更新されるため、古い記事にあるsrc/content/config.tsではなく、現行のContent Collectionsガイドを基準にします。
最小のディレクトリを先に作る
src/
content.config.ts
content/
signalcraft/
first-post.md
layouts/
SignalcraftLayout.astro
pages/
index.astro
signalcraft/
index.astro
[slug].astro
rss.xml.ts
public/
astro.config.mjs
記事の入力はcontent/、HTMLの共通構造はlayouts/、URLはpages/へ分けます。faviconや加工不要の画像はpublic/へ置きます。最初に責務を分けると、記事本文と表示ロジックが一緒に増えにくいです。
src/content.config.tsで入力を検証する
現行のAstroでは、コレクションとloaderをsrc/content.config.tsへ定義できます。最小の例では、タイトル、説明、公開日、タグだけを受け取ります。
import { defineCollection } from "astro:content";
import { glob } from "astro/loaders";
import { z } from "astro/zod";
const signalcraft = defineCollection({
loader: glob({
base: "./src/content/signalcraft",
pattern: "**/*.md",
}),
schema: z.object({
title: z.string().max(60),
description: z.string().optional(),
publishDate: z.coerce.date(),
tags: z.array(z.string()).default([]),
}),
});
export const collections = { signalcraft };
スキーマの役割は、記事をきれいに表示することではありません。
入力ミスをビルド時に検出します。
下書きを除外したい場合は、まずdraftをスキーマへ追加します。
一覧と詳細の両方で同じ条件を使い、スキーマにないfrontmatterを利用側だけで増やしません。
一覧と詳細はgetCollection()から作る
Markdownファイルは、コレクションへ置いただけでは自動的に公開ページになりません。動的ルートでgetStaticPaths()を使い、各エントリをHTMLへ変換します。Content Collectionsの例に近い最小形は次です。
---
import { getCollection, render } from "astro:content";
export async function getStaticPaths() {
const articles = await getCollection("signalcraft");
return articles.map((article) => ({
params: { slug: article.id },
props: { article },
}));
}
const { article } = Astro.props;
const { Content } = await render(article);
---
<article>
<h1>{article.data.title}</h1>
<Content />
</article>
重要なのは、ファイル名からURLを推測しすぎないことです。loaderを変えたときのid、英語のprefix、末尾スラッシュの方針を一度確認し、サイト全体で同じURL関数を使います。
初日に入れる検証
機能を増やす前に、次をビルドへ含めます。
siteを設定したastro.config.mjs- title、description、canonical URL
- sitemapとRSS
- 404ページ
- 見出し、コード、表を読める最小CSS
- pull requestで実行するlintとbuild
siteはcanonical URL、sitemap、RSSの絶対URLに影響します。AstroのConfiguration Referenceで、サイトの公開URLを明示する設定を確認します。
ローカルでは、1記事を追加して次を実行します。
pnpm astro check
pnpm build
プロジェクトにastro checkがない場合は、package.jsonのスクリプトに合わせます。ビルド成功だけでリンクや記事内容が正しいとは限らないため、生成された一覧、詳細、RSSのURLも見ます。
GitHub PagesとCloudflareを比べる
両方とも静的サイトの公開先にできます。差が出るのは、主にURL設定と将来の運用です。
| 観点 | GitHub Pages | Cloudflare Pages / Workers |
|---|---|---|
| 開始点 | GitHubリポジトリ中心 | CloudflareのGitまたはデプロイ設定 |
| 静的配信 | 目的に十分 | 目的に十分 |
| プレビュー | Actionsなどで構成 | pushごとのpreviewを構成しやすい |
| 動的処理 | 別サービスが必要になりやすい | Workersへ拡張できる |
| 注意点 | project siteのbase |
adapterやランタイム依存 |
GitHub Pagesのproject siteでは、siteとbase、内部リンク、RSS、sitemapをリポジトリ名に合わせます。AstroのGitHub Pagesガイドが示す設定を使い、独自ドメインの有無も固定します。
Cloudflareで静的出力だけを配信するなら、まずアダプターなしの構成を試します。サーバー処理やオンデマンドレンダリングが必要になった段階で、Cloudflareのデプロイガイドとadapterの対応を調べる。先に固有APIへ依存すると、移行コストが増えます。
機能は継続できる順に増やす
- Markdownで1本公開します。
- 一覧、詳細、RSS、metadataを確認します。
- CIでlintと
astro buildを実行します。 - 記事数が増えてからタグ、検索、OG画像を追加します。
- 本当に必要になったときだけCMSや動的機能を検討します。
最小構成の目的は、機能を永遠に増やさないことではありません。原稿と公開の経路を短く保ち、次の機能を追加する理由を実際の運用から得ることです。
