head の出典は一つ:SiteHead、JSON-LD のエスケープ、hreflang
三つの HTML シェルが一つのコンポーネントを共有し、head のタグをすべて出力します。データはサーバー層で組み立てます。JSON-LD の山括弧をエスケープする必要がある点も忘れずに。
サイトが最も歪みやすい場所は head です。トップに og:image を足し、記事に JSON-LD を足し、404 ページに半分だけ写す。三ヶ月後には、どのページにどのタグがあるのか誰も説明できなくなります。
出典を一つに
components/SiteHead.astro が head のタグをすべて出力し、データは server/shell.ts の shellHead() が組み立てます。三つの HTML シェル(二つのレイアウトと言語入口ページ)がこれを描画します。SEO の変更はこの二ファイルだけで完結します。
JSON-LD 内のエスケープ
構造化データはインライン JSON なので、シリアライズ後に < を \u003c へ置き換える必要があります。
const json = JSON.stringify(data).replace(/</g, '\\u003c');
置き換えないと、記事タイトルに終了 script タグが含まれた瞬間にタグが閉じ、以降の HTML がすべてスクリプトとして解釈されます。これは理論上の話ではありません。タイトルは著者が自由に書ける入力です。
hreflang と canonical
各ページは三つの hreflang と x-default を出力し、x-default は常に中国語を指します。canonical は www 付きの本番ドメインのみを指します。www なしのドメインは Nginx 層で 301 され、両方を配信すると重複コンテンツになるからです。
robots.txt もビルド生成物
pages/robots.txt.ts が生成し、lib/site.ts の FALLBACK_ORIGIN を参照します。public/ には置きません。理由は実務的で、静的なファイルはドメイン移行時に忘れられますが、生成物は忘れようがありません。
ここまで厳しくする理由
head の誤りには視覚的なフィードバックがありません。og:image が間違っていてもページは正常に見え、壊れるのは共有カードだけです。canonical の誤りは検索エンジンだけが知っています。出典の一意性をハードな制約にすることが、この種の問題を静的に検査する唯一の方法です。

コメント
…