本文へ

開発記録

静的 HTML、canonical、hreflang、sitemap を整合させるには

原稿に記録された静的出力と検証スクリプトをもとに、ページ本文、正規 URL、言語別の代替リンク、sitemap が同じ公開ルートの契約を使う仕組みを整理します。

林予晴
公開
  • Astro
  • 静的サイト
  • SEO の基礎
  • ルート検証

この翻訳は、2026 年 10 月 2 日の原稿に記録された実装と検証を説明しています。サイトの実装についての記述はその記録を指し、現在の公開環境を改めて検証したものではありません。以下の言語プレフィックスがないルート例は、繁体字中国語版のルートです。

静的サイトは、HTML を生成すれば完成というわけではありません。3 言語、旧 URL の互換用入口、Markdown のノートがあるサイトでは、少なくとも 4 つの関連する問いが残ります。読者が受け取る HTML にそのページの内容があるか、正規 URL はどれか、別の言語版が実際に存在するか、そして sitemap にどの URL を載せるかです。

この 4 つを別々に管理すると、矛盾が起きやすくなります。ページは英語なのに canonical が繁体字中国語版を指したり、言語切り替えに存在しない記事の翻訳が表示されたり、正式なルートにはない下書きが sitemap に載ったりします。ここでの判断は、canonical、hreflang、sitemap、静的 HTML は、同じ実際のルート情報と公開データから導く必要があり、4 種類の独立した文言として扱ってはいけないということです。

まず HTML にページの内容があることを確認します

ここで扱うサイトは、Astro の静的出力を使っています。ページコンポーネントはビルド時に実行され、ホーム、固定ページ、ノート一覧、公開記事が直接 HTML を生成します。これは #app のマウント先しかないブラウザー用の外枠とは異なります。読者が最初にドキュメントを受け取った時点で、タイトル、主要な内容、ページ情報を読める必要があります。

出力の検証では、各ページについて次の基本条件を確認します。

  • HTML の lang が正しいこと。
  • ページの主要な h1 が 1 つだけであること。
  • 主要なコンテンツ領域を特定できること。
  • description と、Open Graph の title および description があること。
  • 本文の表示がフレームワークの hydration に依存しないこと。
  • 参照しているローカルのアセットが実際に存在すること。

これらの条件で、まず「この URL が返すドキュメントは読めるページである」と確認します。その後で初めて、検索エンジンや共有サービスにどう理解してもらうかを考える意味があります。canonical は本文のない HTML を救えませんし、sitemap もページそのものの代わりにはなりません。

canonical はインデックス対象のページにだけ出力します

共通 layout は、そのページがインデックス対象かどうかに応じて、canonical、言語別の代替リンク、og:url、構造化データを出力するかを決めます。通常の公開ページでは、その言語に対応する URL を使います。旧ルートの /work は、現在の主要ルートである /about/work を canonical として指定します。

ここには見落としやすい境界があります。HTML を返すすべてのページが、自分を正式なインデックス対象ページとして宣言するべきではありません。

  • 正式な固定ページと公開済み記事は canonical を出力します。
  • dev-only の記事プレビューは noindex, nofollow を出力し、正式な URL を宣言しません。
  • 404 ページは noindex を出力し、ホームを自分の canonical にしません。
  • 旧互換ルートは読める入口として残し、canonical は主要ルートを指します。

プレビューページにも正式な canonical を出力すると、校正用の URL が公開済みコンテンツのように見えます。404 ページの canonical をホームにすると、不明な URL をホームの別の入口として誤って説明することになりかねません。これは SEO の文言の問題ではなく、ページの位置付けを区別できていない問題です。

hreflang は存在する代替ページを示します

固定ページの言語別代替リンクは、言語の集合と固定ページのルートから生成できます。繁体字中国語版の /about、英語版の /en/about、日本語版の /ja/about はいずれも実際のページがあるため、互いを代替版として列挙できます。

記事ページは異なります。記事テンプレートが受け取る translations は、同じコンテンツについて実際に存在する翻訳の集合です。代替リンクはこの集合から生成します。英語の記事がなければ、中国語記事の head に推測で作った /en/notes/... を入れるべきではありません。

この違いによって、hreflang の責任が明確になります。これは言語の一覧でも、「将来あるかもしれないページ」の一覧でもなく、読者が実際に移動できる代替 URL の一覧です。多言語の固定ページはすべての対応版を列挙できますが、多言語記事ではコンテンツのデータに基づいて列挙する必要があります。

sitemap には公開出力だけを載せます

sitemap は、src/content/notes/ のすべてのファイルを走査してそのまま出力するものではありません。まず公開条件を満たす記事を取得し、次を含めます。

  • 各言語の固定ページ。
  • 正式に公開されたノート記事のページ。
  • コンテンツ量が十分な場合のノート一覧のページ分割 URL。

下書き、publishedAt のない記事、公開日時をまだ迎えていない記事、存在しない翻訳は、sitemap に載せるべきではありません。旧 /work の互換用入口も含めません。この入口の役割は既存のリンクを受け止めることであり、新しい主要なインデックス対象 URL になることではないからです。

原稿に記録された実装では、固定ページの URL と記事の URL は異なる方法で生成しています。それでも、公開対象となる条件は一致させる必要があります。正式な build で実際に生成されるページだけに、sitemap に載せる理由があります。

検証スクリプトは何を確認するのでしょうか

このプロジェクトでは、一度 build を実行するだけでなく、検証範囲を分けています。

検証範囲 確認すること
静的出力の検証 固定ページ、互換ルート、404、HTML の内容、metadata、言語指定、ローカルのアセット
ノート出力の検証 公開済み記事のページ、canonical、sitemap、および下書きや未公開本文が漏れていないこと
Content Collection のテスト 日付、slug、stable ID、公開対象の絞り込み、dev-only プレビューなどのデータ契約
build 記録されたコードが想定する静的ルートとアセットを生成できるか

これらの検証は互いの代わりにはなりません。build が成功しても、sitemap に下書きがないことまで自動的に証明するわけではありません。sitemap が正しくても、スマートフォンで内容の順序が読みやすいことまで証明できません。各検証が裏付ける結論は、実際に確認した範囲に限るべきです。

404 とプレビューでは head を分けます

正式なコンテンツ、プレビュー、エラーページにはいずれも HTML がありますが、公開上の位置付けは異なります。そのため layout は notFound、noindex、正式な metadata を分けて扱います。

記事プレビューでは、著者がタイトル、本文、執筆日を確認できる必要があります。一方で、正式な出力、sitemap、検索インデックスから公開済みコンテンツとして扱われるべきではありません。404 ページは、読めるエラーメッセージと閲覧を再開するためのナビゲーションを提供する必要がありますが、ホームの canonical、Open Graph URL、構造化データを出力するべきではありません。

こうした分岐は、head を複雑にするためではありません。「読者に見えること」と「サイトが正式な公開ページとして宣言すること」を分けるためです。プレビューが読めても、それだけで公開コンテンツになるわけではありません。エラーページにナビゲーションがあっても、正常なルートという意味ではありません。

この契約で証明できること、できないこと

原稿に記録されたコードと静的検証は、次の判断を裏付けます。

  • 正式な固定ページと公開済み記事が、読める HTML を生成すること。
  • canonical が主要ルートに従って出力され、旧互換 URL は新しい主要ルートを指すこと。
  • 固定ページと実在する記事の翻訳では、代替リンクの生成元が異なること。
  • sitemap が固定ページと正式な公開記事の集合だけから作られること。
  • 下書きプレビューと 404 が、正式なページのインデックス用 metadata を流用しないこと。

ただし、この証拠から検索順位、インデックス登録の速さ、ソーシャル共有の成果、すべてのクローラーの処理方法を直接導くことはできません。証明しているのは出力の契約が成立していることであり、外部プラットフォームが特定の結果を出したことではありません。

静的な多言語サイトを書くときの確認順序

  1. 各公開 URL が対応する HTML を実際に生成するか確認します。
  2. ページの主要 URL と互換 URL の役割を決めます。
  3. 実在する代替ページにだけ hreflang を出力します。
  4. sitemap に、正式なページと同じ公開対象の集合を読ませます。
  5. プレビューと 404 の noindex ルールを独立させます。
  6. 元のコンポーネントを見るだけでなく、出力検証で HTML、sitemap、アセットを読み戻します。
  7. 機械的な検証、ブラウザー操作、サイト所有者による主観的な確認を分けて報告します。

静的出力の価値は、「サーバーがリクエスト時にページを組み立てなくてよい」ことだけではありません。すべての公開 URL、ページの metadata、コンテンツの状態が、ビルド時点で一致している必要があります。どこかの層が推測に頼っていれば、ページが多く見えても、公開上の位置付けは混乱したままかもしれません。

この記録の範囲

この記事は、原稿に記録された固定ページ、ノート記事、プレビュー、404、canonical、hreflang、sitemap の実装と出力検証を整理したものです。検索エンジンの順位、インデックス登録の結果、共有プラットフォームによる取得、読者の理解への効果が測定済みだとは主張していません。