本文へ移動
Signalcraft
English

← Signalcraft一覧へ戻る

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

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では、sitebase、内部リンク、RSS、sitemapをリポジトリ名に合わせます。AstroのGitHub Pagesガイドが示す設定を使い、独自ドメインの有無も固定します。

Cloudflareで静的出力だけを配信するなら、まずアダプターなしの構成を試します。サーバー処理やオンデマンドレンダリングが必要になった段階で、Cloudflareのデプロイガイドとadapterの対応を調べる。先に固有APIへ依存すると、移行コストが増えます。

機能は継続できる順に増やす

  1. Markdownで1本公開します。
  2. 一覧、詳細、RSS、metadataを確認します。
  3. CIでlintとastro buildを実行します。
  4. 記事数が増えてからタグ、検索、OG画像を追加します。
  5. 本当に必要になったときだけCMSや動的機能を検討します。

最小構成の目的は、機能を永遠に増やさないことではありません。原稿と公開の経路を短く保ち、次の機能を追加する理由を実際の運用から得ることです。