## Why Governance

A free-form tag list is fine for the first ten pages. By the hundredth, you will have `deployment`, `Deployment`, `deploy`, and `deploys` all pointing at the same topic — splitting your tag index into useless near-duplicates and making discovery worse, not better.

Tag governance fixes this by promoting the project's tag set to a **canonical vocabulary** defined in `src/config/tag-vocabulary.ts`. Every tag used in frontmatter is validated against this file. Typos and drift surface as audit findings; legitimate additions are intentional edits to the vocabulary.

The goal is to keep discovery sharp as the doc base grows. Start loose; tighten as you scale.

## The Vocabulary File

`src/config/tag-vocabulary.ts` is an array of `TagVocabularyEntry` objects. Each entry declares a canonical tag id plus optional display metadata:

```ts
{
  id: "deployment",
  label: "Deployment",
  description: "Hosting, CI, and release workflows.",
  group: "topic",
}
```

Content must use `id` exactly. If an id is renamed or removed, update every referencing page in the same change; the old string becomes unknown rather than being rewritten or dropped.

### Extending the Vocabulary in Your Project

After scaffolding with `create-zudo-doc`, **`tag-vocabulary.ts` belongs to your project.** It is a normal source file, not a framework internal. Edit it directly — no forking or monkey-patching required. A typical addition looks like this:

```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",
  },
];
```

After editing, run [`pnpm tags:audit`](https://zudo-doc.takazudomodular.com/docs/guides/tags-audit) to verify nothing unexpected broke, and add tags to pages the usual way:

```mdx
---
title: OAuth 2.0 Setup
tags: [topic:auth, type:runbook]
---
```

## Two Orthogonal Settings

Governance is controlled by two independent fields in `zudoDoc({...})` (set in `zfb.config.ts`):

| Setting          | Type      | Purpose                                                                                    |
| ---------------- | --------- | ------------------------------------------------------------------------------------------ |
| `tagVocabulary`  | `boolean` | Whether the vocabulary file is consulted at all (exact-id recognition and grouping). |
| `tagGovernance`  | `"off" \| "warn" \| "strict"` | Enforcement level when the vocabulary is consulted.                                        |

They are **orthogonal**. `tagVocabulary: false` disables vocabulary entirely, regardless of `tagGovernance`. Leave `tagVocabulary: true` (the default) and tune enforcement via `tagGovernance`.

### The Three Modes

- `"off"` — vocabulary-aware enforcement is skipped. Tags stay completely loose. Useful for legacy migrations or prototypes.
- `"warn"` (default) — `pnpm tags:audit` reports unknown tags and near-duplicates, but `pnpm build` still passes. Fixes can land at your own pace.
- `"strict"` — unknown tags fail Zod validation at `pnpm check` / `pnpm build` time. The vocabulary becomes the single source of truth.

### Recommended Escalation Path

1. **Seed the vocabulary** from the tags you already use — `tag-vocabulary.ts` ships pre-filled with every tag that appears in the default showcase content.
2. **Run `warn` until the audit is clean.** Replace unknown or near-duplicate strings in content with the chosen canonical id.
3. **Flip to `strict`** once the audit is green. From that point on, new tags require a matching vocabulary entry — which is exactly the friction you want to prevent drift.

Adopt `strict` as soon as the backlog is empty; the earlier the constraint is in place, the cheaper it stays.

## Faceted Tag Pattern

Flat tag soups (`deployment`, `advanced`, `tutorial`, `i18n`, ...) scale poorly because the reader cannot tell what a tag answers. A faceted prefix names the axis:

- `type:` — what kind of page is it? `type:guide`, `type:reference`, `type:tutorial`, `type:runbook`.
- `level:` — who is it for? `level:beginner`, `level:advanced`.
- `topic:` — what subject does it cover? `topic:auth`, `topic:ai`, `topic:search`.

The default vocabulary uses this pattern for `type:*` and `level:*` facets. You can extend it with your own `topic:*` entries, or introduce new facets (`product:*`, `team:*`) as your doc base grows. Facets stay separate in the grouped footer taglist — see [Footer taglist](https://zudo-doc.takazudomodular.com/docs/guides/footer-taglist).

## Next Steps

- [Tag audit](https://zudo-doc.takazudomodular.com/docs/guides/tags-audit) — what `pnpm tags:audit` reports and how to read it.
- [Tag suggestions](https://zudo-doc.takazudomodular.com/docs/guides/tags-suggest) — opt-in local LLM suggester for new pages.
- [Footer taglist](https://zudo-doc.takazudomodular.com/docs/guides/footer-taglist) — surface the vocabulary to readers.