## Overview

The footer taglist is an optional index of tags rendered inside the existing footer grid. It gives readers a persistent way to reach every tag page without leaving the current doc.

It is **off by default** — the footer looks the same as before until `footer.taglist.enabled` is set to `true` in `zfb.config.ts`. On a fresh scaffold, that setting alone renders an empty taglist: its chrome has no tag loader or vocabulary binding. Nothing about the per-page tag badge row or the homepage "All Tags" section changes.

## Enabling

Add a `taglist` block to the existing `footer` config:

```ts
footer: {
  links: [
    // ...existing footer link columns
  ],
  copyright: `Copyright © ${new Date().getFullYear()} Your Project.`,
  taglist: {
    enabled: true,
    title: "Tags",
    groupBy: "group",
    groupTitles: {
      topic: "By topic",
      type: "By type",
      level: "By level",
    },
    locales: {
      ja: {
        title: "タグ",
        groupTitles: {
          topic: "トピック別",
          type: "種類別",
          level: "レベル別",
        },
      },
    },
  },
},
```

Each field is optional except `enabled`. Sensible defaults take over for anything you omit.

[Dynamic content unavailable in text export]

`loadTagsForLocale` and `tagVocabulary` default to no-op data. Point
`chromeBindingsModule` at a module that binds both slots. Fresh route stubs
already consume it; do not edit them. See [Custom Components](https://zudo-doc.takazudomodular.com/docs/guides/custom-components)
and [Host Chrome Bindings](https://zudo-doc.takazudomodular.com/docs/reference/host-chrome-bindings).



Add a bindings module that provides the vocabulary and a locale-aware count loader. The
loader contract is exactly `(lang: string) => readonly { tag: string; count: number }[]`;
derive its entries from your content collection rather than returning a static list.

```ts title="src/chrome-bindings.ts"
import { defineChromeBindings } from "@takazudo/zudo-doc/chrome-bindings";
import { tagVocabulary } from "./tag-vocabulary";
import { collectTagsForLocale } from "./tag-data";

function loadTagsForLocale(
  lang: string,
): readonly { tag: string; count: number }[] {
  return collectTagsForLocale(lang).map(({ tag, count }) => ({ tag, count }));
}

export const chromeBindings = defineChromeBindings({
  loadTagsForLocale,
  tagVocabulary,
});
```

Point `zudoDoc()` at that module and pass the same vocabulary to its build-time tag
configuration:

```ts title="zfb.config.ts"
import { defineConfig } from "zfb/config";
import { zudoDoc } from "@takazudo/zudo-doc/config";
import { tagVocabulary } from "./src/tag-vocabulary";

export default defineConfig(
  zudoDoc({
    // ...your settings, including footer.taglist.enabled: true
    tagVocabulary: true,
    tagVocabularyEntries: tagVocabulary,
    chromeBindingsModule: "./src/chrome-bindings.ts",
  }),
);
```

## `groupBy: "group"` vs `"flat"`

The taglist can render in two modes.

- **`groupBy: "group"`** — one column per vocabulary `group`, in the order the groups first appear in the vocabulary you bind. This is the default whenever the vocabulary is active (`tagVocabulary: true` and `tagGovernance !== "off"`). Each column's title comes from `groupTitles[<group>]`, falling back to a capitalised version of the group name (`topic` → `Topic`).
- **`groupBy: "flat"`** — a single alphabetised column titled `title`. Forced when the vocabulary is inactive, and a useful choice when you have fewer than a handful of tags and grouping would look sparse.

Pick `"group"` once you have enough tags that a grouped view actually separates topics from types. Stick with `"flat"` until then.

This repository's `src/config/tag-vocabulary.ts` is a showcase-only worked example; a
fresh scaffold has no `src/config/` directory. Create your vocabulary wherever it fits your
project and wire it through `tagVocabularyEntries` and `chromeBindings` as above.

## Locale Overrides

Column titles are the only strings the taglist shows, so locale overrides stay small. The `locales` map keys on locale code (matching [`locales` in settings](https://zudo-doc.takazudomodular.com/docs/guides/configuration)):

```ts
taglist: {
  enabled: true,
  title: "Tags",
  groupTitles: { topic: "By topic", type: "By type", level: "By level" },
  locales: {
    ja: {
      title: "タグ",
      groupTitles: { topic: "トピック別", type: "種類別", level: "レベル別" },
    },
  },
},
```

Only keys present in the locale object override the default-locale strings; missing keys fall back. Tag ids themselves are **not** translated — see the [i18n section of the tags guide](https://zudo-doc.takazudomodular.com/docs/guides/tags#i18n-behavior) for the reasoning.

## What Readers See

Every vocabulary tag that at least one non-draft, non-unlisted page references appears as a link to that tag's index page (`/docs/tags/<id>/` or `/{locale}/docs/tags/<id>/`). Empty groups collapse — you only pay for the columns you fill.

## Related

- [Tag governance](https://zudo-doc.takazudomodular.com/docs/guides/tag-governance) — the vocabulary and group declarations that shape the taglist.
- [Tags](https://zudo-doc.takazudomodular.com/docs/guides/tags) — the per-page tag badge row and homepage tag index.
- [Footer](https://zudo-doc.takazudomodular.com/docs/guides/footer) — the rest of the footer configuration.