症状

公開前の記事3本に draft: true を付けて置いておいた。トップの一覧にもRSSにも出ない。

下書きとして機能しているように見える。

ところが、個別URLを直接叩くと普通に表示される。さらにsitemapを見ると、ドラフトのURLがしっかり載っていた。

つまり「見せていないつもりの記事」が、検索エンジンには案内済みという状態。

draft: true 一覧 出ない RSS 出ない 個別URL 見える sitemap 載る
図1: 出口は4つあるのに、遮断されていたのは上の2つだけ。下の2つは開けっぱなしだった。

検証環境

create astro のblogテンプレートから立ち上げた静的ブログ(Astro 7.2.4)。

記事はコンテンツコレクション管理で、frontmatterに draft フラグを追加した構成。

原因候補と確認したこと

最初の想定は「draftフラグの書き方を間違えた」。でもfrontmatterは正しい。

一覧とRSSからはちゃんと消えている。

そこで除外処理がどこに入っているかを数えた。一覧ページ: ある。

RSS: ある。個別ページの動的ルート: ない。

sitemap: 生成されたページを全部拾うだけなので、当然ない。

実際の原因

テンプレートのdraft除外が「一覧系」にしか入っていなかった。

個別ページを作る動的ルート([...slug].astro)の getStaticPaths は全記事分のページを生成していて、sitemapインテグレーションはその生成結果をそのまま反映する。

「下書き」という機能があるのではなく、「一覧から隠す処理」が2箇所に書いてあっただけ、というのが正体。

解決方法と解決確認

動的ルート側の getStaticPaths に本番ビルド時のみのdraft除外を追加した。

開発サーバーでは従来どおり閲覧できるようにして、レビュー用途は残した。

再ビルドしてdistを走査するとdraft記事3本が消え、sitemapからもURLが消えた。

開発環境では3本とも表示できることも確認。

今回得たEXP

「一覧に出ない」と「公開されない」は別物。

draftのような除外系の機能は、出口の数(一覧・RSS・個別ページ・sitemap)を数えて、全部で除外されているか確認してから信じる。

EXITS ×4 一覧 RSS 個別ページ sitemap
図2: 囲いは出入口の数だけ点検する。4つ全部にチェックが付いてから「下書き」を信じる。

現場でいうと、立入禁止の看板を正門にだけ立てて、裏口と通用口が開けっぱなしになっていた状態。

囲いは出入口の数だけ点検する。

ちなみにこの漏れを見つけたのは、記事ドラフトを書かせていたAI相棒だった。

「draftなのにsitemapに載る」と自分で気づいて直してきた。囲いの点検は任せられる時代になっている。