タグガバナンス
ボキャブラリを整備しビルド時に検証することで、数ページから数百ページまでタグ付けをスケールさせる。
なぜガバナンスが必要か
最初の10ページほどであれば、自由記述のタグリストで十分です。しかし100ページを超えた頃には、deployment、Deployment、deploy、deploysが同じトピックを指しているのに別々のタグとして扱われるようになります。その結果、タグインデックスは役に立たないほぼ重複したエントリで分断され、発見性は向上するどころか悪化します。
タグガバナンスは、プロジェクトのタグセットをsrc/で定義された正規ボキャブラリに格上げすることでこの問題を解決します。フロントマターで使われるすべてのタグはこのファイルに対して検証されます。タイポやドリフトは監査結果として表面化し、正当な追加はボキャブラリへの意図的な編集となります。
目的は、ドキュメントベースが成長するなかで発見性を鋭く保つことです。緩く始めて、スケールに合わせて締めていきます。
ボキャブラリファイル
src/はTagVocabularyEntryオブジェクトの配列です。各エントリは正規タグ id、任意の表示ラベル、グループ、そしてコンテンツ側で使用を許可するエイリアスを宣言します。
{
id: "deployment",
label: "Deployment",
description: "Hosting, CI, and release workflows.",
group: "topic",
aliases: ["deploy", "deploys"],
}
既存ページを壊さずにタグを段階的に廃止するには、deprecated としてマークするか、代替タグへリダイレクトします。エントリを黙って削除してはいけません。フェーズアウト契約の全文はsrc/のインラインコメントを参照してください。
プロジェクト側でボキャブラリを拡張する
create-zudo-docでスキャフォールドしたあとは、tag-vocabulary.tsはあなたのプロジェクトのものです。 フレームワーク内部ではなく普通のソースファイルです。フォークやモンキーパッチは不要で、直接編集してください。典型的な追加は次のような形になります。
export const tagVocabulary: readonly TagVocabularyEntry[] = [
// ...existing entries
{
id: "topic:auth",
label: "Auth",
description: "Authentication, sessions, SSO.",
group: "topic",
},
{
id: "type:runbook",
label: "Runbook",
description: "Incident response and on-call procedures.",
group: "type",
},
];
編集後は<code>pnpm tags:audit</code>を実行して想定外の破壊がないか確認し、通常どおりページにタグを付けます。
---
title: OAuth 2.0 Setup
tags: [topic:auth, type:runbook]
---
独立した2つの設定
ガバナンスはsrc/にある独立した2つの設定で制御します。
| 設定 | 型 | 目的 |
|---|---|---|
tagVocabulary | boolean | ボキャブラリファイルを参照するかどうか(エイリアス解決、deprecation、グルーピング)。 |
tagGovernance | "off" | "warn" | "strict" | ボキャブラリが参照される場合の検証レベル。 |
この2つは直交しています。tagVocabulary: falseにするとtagGovernanceの値に関わらずボキャブラリは完全に無効になります。通常はデフォルトのtagVocabulary: trueのままにし、tagGovernanceで強度を調整します。
3つのモード
"off"— ボキャブラリを用いた検証を行いません。タグは完全に緩いままです。レガシー移行やプロトタイプで有用です。"warn"(デフォルト) —pnpm tags:auditが未知タグ、deprecation、ニアデュプリケートを報告しますが、pnpm buildは通過します。修正は自分のペースで進められます。"strict"— 未知タグはpnpm check/pnpm build時に Zod バリデーションで落ちます。ボキャブラリが唯一の真実となります。
推奨エスカレーションパス
- すでに使っているタグからボキャブラリをシードする。 デフォルトのショーケースコンテンツに登場するすべてのタグは
tag-vocabulary.tsに最初から入っています。 - 監査がクリーンになるまで
warnで運用する。 unknown を解消し、pnpm tags:audit --fixでエイリアスを書き換え、ニアデュプリケートは正規 id のエイリアスとして吸収します。 - 監査がグリーンになったら
strictに切り替える。 以降、新しいタグには必ずボキャブラリエントリが必要になります——ドリフトを防ぐためにちょうど良い摩擦です。
バックログが空になり次第strictを採用してください。制約が入るのは早ければ早いほど安価です。
ファセットタグのパターン
フラットなタグの海(deployment、advanced、tutorial、i18n……)はスケールしません。読者からはタグが何を答えるのかが判別できないからです。ファセットプレフィックスは軸の名前を明示します。
type:— どんな種類のページか?type:guide、type:reference、type:tutorial、type:runbook。level:— 誰向けか?level:beginner、level:advanced。topic:— どのテーマを扱うか?topic:auth、topic:ai、topic:search。
デフォルトのボキャブラリはtype:*とlevel:*のファセットにこのパターンを使っています。独自のtopic:*エントリを足したり、ドキュメントベースが育ったら新しいファセット(product:*、team:*)を導入したりできます。ファセットはグループ化されたフッタータグリストで別々に並びます——フッタータグリストを参照してください。