Skip to content
ソフトウェア自動開発のメモ帳

Astro ブログのデファクト標準構造を調べて整えた話

CSS ゼロのブログに、テーマを入れたくなった

Astro で作ったブログに CSS を一切書いていなかった。セマンティック HTML だけで構成されていて、機械には読めるが人間には読みにくい。そろそろスタイリングが必要だ。

Astro にはテーマがある。テーマがあるということは、テーマが前提とする標準的な構造があるはずだ。その構造を知らずに独自の構成でブログを作り込むと、後からテーマを適用しようとしたときにコンテンツの書き直しが発生する。それは避けたい。

テーマを入れる前に、まずデファクト標準を調べることにした。

人気テーマを分析してデファクト標準を特定する

調べたのは、AstroPaper、Astro Cactus、AstroWind、Astro 公式ブログスターターの 4 つ。コミュニティで人気のテーマと公式テンプレートを並べれば、共通パターンが見えてくるはずだ。

結果はこうなった。

要素AstroPaperAstro CactusAstroWind公式スターター
Base + Post 二層レイアウト
説明文フィールド必須
コレクション名 blog××
更新日フィールド(任意)
代表画像フィールド(任意)

フィールド名はテーマごとに微妙に異なる(heroImage / ogImage / coverImage など)が、概念としての構造は共通している。ここから互換性の高い構成を抽出した。

ギャップ分析と変更

自分のブログの構成とデファクト標準を突き合わせた。

項目デファクト標準変更前変更後
レイアウトBase + Post 二層ページごとに HTML 出力Base.astro + PostLayout.astro
description必須なしスキーマに必須フィールドとして追加
コレクション名blogpostsblog
updatedDate任意なしスキーマに任意フィールドとして追加
heroImage任意なしスキーマに任意フィールドとして追加
ルーティング/posts/[slug]/posts/[slug]変更不要

スキーマは以下の形に落ち着いた。

const blog = defineCollection({
  schema: ({ image }) => z.object({
    title: z.string(),
    description: z.string(),
    pubDate: z.coerce.date(),
    updatedDate: z.coerce.date().optional(),
    tags: z.array(z.string()),
    draft: z.boolean().default(false),
    heroImage: image().optional(),
  }),
});

レイアウトの二層構造はこう分離される。

Base.astro:       <html><head>...</head><body><slot /></body></html>
PostLayout.astro: <Base><article><Content /></article></Base>

Base がサイト共通の HTML 構造を持ち、PostLayout が記事のメタ情報(タイトル、公開日、タグ)と本文を配置する。ページを追加するときは Base だけを使い、記事ページでは PostLayout を通して Base を使う。責務が明確に分かれる。

AstroPaper テーマで互換性を検証する

構造を整えたら、実際にテーマが動くか検証する。AstroPaper を選んだ理由は、コミュニティで最も人気があり、コレクション名 blog とルーティング /posts/[slug] がそのまま一致するからだ。

AstroPaper は Tailwind CSS に依存しているため、依存関係として追加した。テーマのレイアウトとコンポーネントを移植し、既存のコンテンツがそのまま表示されることを確認した。

興味深かったのは、フィールド名の差異の吸収方法だ。AstroPaper は内部的に pubDatetime というフィールド名を使っているが、自分のスキーマでは pubDate を使っている。同様に画像フィールドもテーマごとに heroImageogImagecoverImage と名前が異なる。これらの差異はコンテンツのスキーマを変更するのではなく、コンポーネント側で吸収した。コンテンツは共通の最小構成のまま、テーマ側のコンポーネントが自分のスキーマに合わせて読み替える。

これが標準構造の価値だ。テーマを変えるとき、変更するのはレイアウトとコンポーネントであって、コンテンツではない。 コンテンツが標準構造に従っていれば、テーマの差し替えはコンポーネントの差し替えで完結する。

まとめ

Astro ブログのテーマ互換性を確保するための構造は、シンプルだ。

テーマを変えるとき、コンテンツを書き直す必要がなくなる。構造が標準に従っていれば、テーマの切り替えはコンポーネントの入れ替えだけで済む。


参考リンク