第31回 記事のFrontmatterチェックを強化する―カテゴリ・連載・タグの設定ミスをビルド前に検出

Cloudflare WorkersのビルドでseriesOrder重複を検出した経験から、FrontmatterをAstro build前に検査する処理を追加。category、subcategory、series、seriesOrder、tagsを既存schemaとtaxonomyで確認し、正常時の219ページ生成まで記録します。

執筆:ゆまラボ運営者

公開:更新:
第31回 記事のFrontmatterチェックを強化する―カテゴリ・連載・タグの設定ミスをビルド前に検出

第30回では、タグ一覧へ検索と並び替えを追加し、記事末尾には既存の分類情報から関連記事を表示するようにした。その作業を進める中で、記事側のFrontmatterがサイト全体の分類や連載順へ直接影響する場面も増えてきた。

そして実際に、記事を追加してCloudflare Workersへ反映しようとしたところ、最新ビルドが失敗した。

今回のエラーは、Cloudflareで止まったこと自体は悪くない。誤った連載順のまま公開されず、ビルド処理が問題を検出してくれたからだ。

ただし、気付いたのはpush後のCloudflare。

記事を追加

push

Cloudflare Workersでビルド

Frontmatterの設定ミスを検出

この流れなら公開事故は防げるが、修正するにはローカルへ戻り、Frontmatterを直し、もう一度確認することになる。毎回pushした後に気付くのは、さすがに手間がかかる。そこで第31回では、同じ種類のミスをnpm run buildの本処理へ入る前にローカルで検出できるようにする。

過去にもFrontmatterまわりでは何度か修正している。第12回 Cloudflareビルド失敗を修正―Astroのカテゴリ・タグ・トップページも見直すではContent Collection schemaと合わないカテゴリ値でビルドが止まり、第16回 Astroブログのタグ重複を仕組みで防ぐ―タグマスタ、alias、正規化処理を追加ではタグを共通ルールで扱う処理を追加した。

今回はそれらを置き換えず、現在のschemaとtaxonomyを使った事前検査を追加する。

Cloudflareのビルドが連載順の重複を止めた#

修正前のCloudflare Workersでは、最新ビルドが失敗していた。

Cloudflare Workersでビルドが失敗した状態。公開不要な作者名とアカウント名はマスク済み

ログを見ると、今回止まった理由は依存関係やWranglerではない。

連載順が重複しています:
astro-cloudflare-site-build:30
(29-tag-list-related-articles, 29-heading-anchor-link-copy)

同じastro-cloudflare-site-buildの中でseriesOrder: 30が2記事に設定されていた。

同一連載でseriesOrder 30の重複を検出してビルドが停止したログ

このエラー表示は役に立つ。連載ページはseriesOrderを基準に並べるため、重複した状態を通すより、ビルドを失敗させて修正対象を明示した方が安全だ。

一方、検出位置はAstro build中。Cloudflareでログを見るまで設定ミスに気付かなければ、修正のたびにpushとリモートビルドを挟むことになる。

第26回では、生成後のHTMLに壊れた内部リンクがないかをビルド時に検査する処理を追加した。今回はそれより前、Markdownを読み込んだ段階で確認できるFrontmatterを対象にする。

Frontmatterだけを先に検査するコマンドを追加する#

Codexには、現在のpackage.json、Content Collection schema、taxonomy.tssrc/utils/posts.tsscripts/verify.mjsを先に確認させた。

新しいルールを別管理するのではなく、現在の定義をそのまま使うことを条件にした。

実装後はFrontmatterだけを検査する専用コマンドを実行できる。

npm run check:frontmatter

追加されたcheck-frontmatter.mjsでは、実際のContent Collection schemaを使いながら、次を確認する。

category
subcategory
series
seriesOrder
tags

categorysubcategoryは、形式だけ合っていればよいわけではない。現在登録されているtaxonomyと一致するかまで確認する。

seriesも同様で、存在しない連載名を通さない。seriesOrderはseriesとの組み合わせ、正の整数かどうか、同一連載内での重複を確認する。

タグについては第16回で追加したtagMaster、alias、正規化処理を再利用した。新しいタグ管理方式を追加していない。

ERRORとWARNINGを分ける#

今回の検査では、すべての指摘をERRORにはしていない。

連載順の重複や存在しないcategoryなど、ビルドを続けると構造上の問題になるものはERRORとして扱う。一方、既存の未登録タグはこれまでと同じWARNINGのままにした。

ここを勝手にERRORへ変更すると、現在残っているタグ警告だけでビルドが止まる。今回の目的はFrontmatter検査を前倒しすることで、既存の警告運用まで変更することではない。

実装後にnpm run check:frontmatterを実行した結果は次の状態。

PASS     71記事
WARNING  130件
ERROR    0件

Frontmatter単独チェックの実行結果。71記事を確認し、既存の未登録タグをWARNINGとして表示

WARNINGには、SEOGoogle SearchGeminirobots.txtAIクローラーなど、現在のtagMasterに未登録のタグが含まれている。

表示は増えているが、ここでは問題を隠さない。どの記事にどの未登録タグがあるかを事前に一覧で確認できる状態にしたうえで、既存仕様どおりビルドは継続できる。

npm run buildの前に自動実行する#

専用コマンドを毎回手で実行するだけでは、実行を忘れれば以前と同じ状態になる。

そこでpackage.jsonprebuildを追加し、通常どおり、

npm run build

を実行しただけでFrontmatter検査が先に動くようにした。

処理の順番は次の形になる。

npm run build

prebuild

Frontmatterチェック

ERRORあり → 非0終了して停止
ERRORなし → Astro build開始

Pagefind・リンク検査まで続行

Cloudflareで見つかったseriesOrder重複も、この段階で止められる。

Codexではテスト用に一時的な重複を作り、npm run buildを実行した。結果はERRORで終了し、Astro buildは開始しなかった。テスト後は記事を元に戻している。

つまり、以前はAstro側のgetPostsまで進んでから出ていた同じ種類の重複を、現在はprebuildで先に検出できる。

Astro build中の既存チェックも残す#

事前チェックを追加したからといって、既存のsrc/utils/posts.ts側の検査を削除したわけではない。

Codexの報告では、seriesOrder重複検査を共通化しつつ、Astro build中の既存検査も維持している。

事前チェックは早く気付くための入口で、既存チェックを無効化する変更ではない。

この構成なら、通常の作業ではprebuildで止まり、何らかの経路で事前検査を通さずAstro側の処理へ入った場合にも既存検査が残る。

正常なFrontmatterで219ページを生成する#

一時テストを戻した後、正常な状態でnpm run buildを実行した。

Frontmatter検査を通過したあと、Astro build、画像生成、sitemap、Pagefindまで進んでいる。

Pagefindの出力では、219個のHTMLを確認し、71ページを検索対象としてインデックスしている。

Frontmatter検査後にPagefindと内部リンク検査まで完了した状態

同じ画面では内部リンクも、

Checked 219 HTML pages
8393 internal links
broken links: 0

まで確認できた。

最終的なAstroのビルド結果も成功している。

Astro buildが219ページ生成して完了した状態

ログでは以下を確認した。

219 page(s) built in 27.51s
[build] Complete!

新規npmパッケージは追加していない。lockfileも変更なし。RSS、sitemap、Pagefind、OGP、URL、UI、Cloudflare Workersの設定も今回の対象外としてそのまま残している。

verify.mjsの既存エラーは別に残す#

今回の作業とは別に、既存のnode scripts/verify.mjsは現在も停止する。

対象はcodex-luna-astra-astro-comparisonで、pubDate: 2026-09-09updatedAt: 2026-09-12が異なることを検証側がエラーとして扱っている。

これはFrontmatter事前検査を追加したことで発生したものではないため、今回の作業では変更していない。

新しいチェックを追加したときに、既存の別エラーまで同じ作業で直すと、何を変更した回なのか分かりにくくなる。今回は、

Frontmatter事前チェック
→ 実装・確認

verify.mjsの既存エラー
→ 別件として残す

と分けた。

Frontmatter事前検査の変更点#

Cloudflare WorkersでseriesOrder重複を検出できたことで、ビルドを失敗させる検査そのものは有効だと確認できた。

今回追加したのは、その検出をローカルへ前倒しする仕組みになる。

npm run check:frontmatterでは71記事を確認し、既存の未登録タグ130件をWARNINGとして表示、ERRORは0件。prebuildへ接続したことで、通常のnpm run buildでも同じ検査が自動で先に実行される。

検査対象はcategorysubcategoryseriesseriesOrdertags。Content Collection schemaと既存taxonomy、tagMaster、alias、正規化処理を再利用し、記事ごとの新しい管理項目は追加していない。

意図的に連載順を重複させたテストではAstro build開始前に停止し、元へ戻した正常状態では219ページを生成してPagefindまで完了した。内部リンク8,393件も壊れたリンク0件になっている。

Cloudflareで止められる状態は残したまま、同じ設定ミスをローカルでも先に見つけられるようになった。