> ## Documentation Index
> Fetch the complete documentation index at: https://docs.livepeer.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Component Governance Framework

> Canonical reference for how components are classified, built, documented, and maintained in snippets/components/.

# Component Governance Framework

**Repository:** `livepeer/docs`, `docs-v2` branch\
**Scope:** `snippets/components/` – the governed component library\
**Platform:** Mintlify (MDX-based)\
**Version:** 1.0\
**Date:** 7 March 2026\
**Author:** Wonderland (Alison Haire) / Claude collaboration\
**Source deliverables:** D1–D6 of the Component Governance Framework plan

<CustomDivider />

## Quick Start

You're a contributor. You want to build, use, or modify a component. Here's everything you need in 60 seconds.

### Find a component

Use the [Component Registry](/docs-guide/config/component-registry.json) or the published [Component Library](/v2/resources/documentation-guide/component-library) pages. Every component has a status badge, props table, and copy-paste example.

### Use a component

Import with the full explicit path in your MDX page:

```mdx icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
import { CustomDivider } from '/snippets/components/elements/spacing/Divider.jsx'

<CustomDivider />
```

Mintlify requires full paths with file extensions. No barrel imports. Inter-component imports via absolute `/snippets/` paths are permitted – the importing component handles its own dependencies, so the consuming MDX page does not need to re-import sub-components used internally. Circular imports are not allowed. Shared non-visual runtime logic may be kept inline in the exported component or imported from a colocated non-component `.js` helper module.

### Decide which category

Follow the decision tree (first match wins):

1. **Fetches, embeds, or binds to external/third-party data?** → `integrators/`
2. **Part of the page's outer structure, typically used once?** → `scaffolding/`
3. **Takes content and presents it in a formatted way?** → `displays/`
4. **Exists to hold, group, or arrange other things?** → `wrappers/`
5. **Single visual piece – no wrapping, no arranging, no fetching?** → `elements/`

### Build a new component

1. Create your `.jsx` file in the correct category folder.
2. Use arrow function syntax (`export const X = () => ...`).
3. Add the full JSDoc block (6 governance fields + `@aiDiscoverability` if hook-using + `@param` per prop + `@example`).
4. Use `var(--lp-*)` CSS tokens for all colours. No hardcoded hex. No ThemeData.
5. Add defensive rendering – guard all props, never throw. A crash kills the entire page.
6. Create an example in `{category}/examples/{file}-examples.mdx`.
7. Write unit tests in `operations/tests/unit/components/{category}/{file}.test.js`.
8. Verify visually in both light and dark mode via `mintlify dev`.
9. Commit. Pre-commit validates JSDoc, regenerates the registry, and checks styling rules.

### Component checklist (full)

```icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
JSDoc
  □ All 6 governance fields present (+ @aiDiscoverability if hook-using)
  □ @param for every prop
  □ @example with primary usage

Props
  □ camelCase names
  □ Boolean props: is/has prefix
  □ Handler props: on prefix
  □ Defaults in destructuring
  □ children for slot content, named props for data
  □ Spread last (...rest)
  □ Required props: no default. Optional: always have default.

Composition
  □ Inter-component imports use absolute `/snippets/` paths only
  □ No circular imports between `.jsx` component files
  □ Shared runtime logic for MDX-facing components stays inline or comes from a colocated `.js` helper import
  □ Renders correctly standalone and inside Mintlify globals

Styling
  □ Colours use var(--lp-*) tokens
  □ No ThemeData, no hardcoded hex, no !important
  □ Dark/light mode works (tokens + Tailwind dark:)

Error Handling
  □ Null-safe prop access throughout
  □ Required props guarded – returns null if missing
  □ Array operations guarded: (items ?? []).map()
  □ Try-catch wraps complex logic
  □ console.warn on degradation
  □ Never throws

Accessibility
  □ Semantic HTML elements
  □ Images have alt text
  □ [If interactive] ARIA attributes present
  □ [If interactive] Keyboard operable

Testing
  □ Visual verification: light and dark mode
  □ Browser test coverage: page renders
  □ Unit tests: valid props, no props, null data, missing required
```

<CustomDivider />

## 1. Classification & Purpose Model

### 1.1 Category Taxonomy

Six categories. Every component belongs to exactly one.

| Category        | Folder         | Purpose                                                                              |
| --------------- | -------------- | ------------------------------------------------------------------------------------ |
| **Elements**    | `elements/`    | Standalone visual atoms – icons, text, callouts, links, images, math, dividers, a11y |
| **Wrappers**    | `wrappers/`    | Containers that hold, group, or spatially arrange other components                   |
| **Displays**    | `displays/`    | Renderers for authored content – code, video, diagrams, quotes, response fields      |
| **Scaffolding** | `scaffolding/` | One-per-page structural skeleton – heroes, portals, frame-mode overrides             |
| **Integrators** | `integrators/` | Fetches, embeds, or binds to external data – feeds, embeds, video, APIs              |
| **Config**      | `config/`      | Non-component configuration objects (e.g. theme, colour maps)                        |

### 1.2 Decision Tree

Classify by answering in order. First match wins.

```icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
Q1: Fetches, embeds, or binds to external/third-party data?
    YES → INTEGRATORS

Q2: Part of the page's outer structure, typically used once?
    YES → SCAFFOLDING

Q3: Takes content and presents it in a formatted way?
    YES → DISPLAYS

Q4: Exists to hold, group, or arrange other things?
    YES → WRAPPERS

Q5: Default → ELEMENTS
```

**Order rationale:** Integrators and Scaffolding are checked first because they're the most constrained (fewest false positives). Displays catches formatting/rendering components. Wrappers catches spatial arrangement. Elements is the default atom.

### 1.3 Library Boundary

**Inside:** `snippets/components/` and its six category subdirectories. Every exported component here is governed.

**Outside (not governed by this framework):**

| Pattern                                        | Governed by                                                                   |
| ---------------------------------------------- | ----------------------------------------------------------------------------- |
| Mintlify globals (Card, Tabs, Accordion, etc.) | Mintlify platform                                                             |
| MDX composables (`snippets/composables/`)      | Composable Content Structure – see [Section 12](#12-composable-content-layer) |
| Data snippets (`snippets/data/`)               | Data integration layer                                                        |

Mintlify enforces that all importable JSX lives under `/snippets/`. No "section-local components" are possible outside this path.

### 1.5 Data & Props Surface

Prop inputs are documented via `@param` tags on each exported component. For integrators, `@dataSource` identifies the external pipeline or API. See Section 5.2 for the full 6-field schema.

<CustomDivider />

## 2. Repo Structure & Documentation Architecture

### 2.1 Folder Layout

```icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
snippets/components/
├── elements/          # Visual atoms – icons, text, links, callouts, math, spacing
│   ├── icons/
│   ├── links/
│   ├── spacing/
│   └── ...
├── wrappers/          # Containers that group or arrange other components
│   ├── cards/
│   ├── grids/
│   ├── tables/
│   └── ...
├── displays/          # Content renderers – code, video, diagrams, quotes
│   ├── code/
│   ├── media/
│   └── ...
├── scaffolding/       # One-per-page structure – heroes, portals, frame-mode
│   ├── frame-mode/
│   └── ...
├── integrators/       # External data – feeds, embeds, APIs
│   ├── embeds/
│   └── ...
├── config/            # Non-component configuration objects
└── x-archive/         # Superseded files (retained until final cleanup)
```

Sub-niche folders within each category. One `examples/` subdirectory per category where the category uses runnable examples.

### 2.2 Naming Conventions

| Element       | Convention                        | Example                                |
| ------------- | --------------------------------- | -------------------------------------- |
| Files         | PascalCase `.jsx` (canonical)     | `FrameMode.jsx`, `StarfieldCanvas.jsx` |
| Exports       | PascalCase, named, arrow function | `export const PageHeader = () => ...`  |
| Example files | kebab-case `-examples.mdx`        | `frame-mode-examples.mdx`              |

### 2.3 File Granularity

Grouped files with per-export JSDoc. Related components share a file. Each export gets its own 6-field JSDoc block. Non-exported helpers are implementation details.

### 2.4 Import Paths

Full explicit paths. Mintlify requires file extensions. No barrel imports.

```jsx icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
import { CustomDivider } from '/snippets/components/elements/spacing/Divider.jsx'
import { StyledTable, TableRow } from '/snippets/components/displays/tables/Tables.jsx'
```

### 2.5 Documentation Architecture

```icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
JSDoc (SOT for metadata + props)
    ↓
docs-guide/config/component-registry.json (generated by pre-commit)
    ↓
Published MDX pages (generated, LLM editorial + template fallback)
```

Per-folder READMEs are deprecated. The registry and published pages are the two documentation surfaces.

### 2.6 Registry

Single JSON at `docs-guide/config/component-registry.json`. Generated by pre-commit hook when files in `snippets/components/` are staged. Contains all 6 enforced governance fields per component plus derived fields (`file`, `importPath`). Script: `operations/scripts/generators/components/library/generate-component-registry.js`.

<CustomDivider />

## 3. Styling Architecture & Standards

### 3.1 Three-Layer Hierarchy

```icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
Layer 1: Mintlify Theme (docs.json) – platform colours, layout, dark mode toggle
Layer 2: style.css (repo root) – --lp-* CSS custom properties, Mintlify overrides
Layer 3: Component styles – consume tokens, scoped vars if documented
```

Components consume `var(--lp-*)` tokens. They rarely define new variables (only for computed/dynamic values, with documentation).

### 3.2 Token Namespace

All tokens use `--lp-` prefix: `--lp-color-*`, `--lp-spacing-*`, `--lp-font-*`, `--lp-radius-*`, `--lp-shadow-*`, `--lp-z-*`.

Every `--lp-color-*` token has both light and dark values defined in `style.css`.

### 3.3 Banned Patterns (Pre-commit Blocks)

| Pattern               | Why                                            |
| --------------------- | ---------------------------------------------- |
| **ThemeData**         | Deprecated, causes bugs                        |
| **Hardcoded hex/rgb** | Breaks dark mode, prevents centralised updates |
| **`!important`**      | If you need it, the hierarchy is wrong         |

### 3.4 Advisory Patterns (Code Review Flags)

| Pattern                             | Guidance                                         |
| ----------------------------------- | ------------------------------------------------ |
| **Static inline `style={}`**        | "Could this be a `var(--)` token?"               |
| **Direct Mintlify class overrides** | Should go through `style.css`, not component JSX |

### 3.5 Dark/Light Mode

| Concern                   | Mechanism                                                       |
| ------------------------- | --------------------------------------------------------------- |
| Colour values             | `var(--lp-color-*)` tokens – automatic light/dark swap          |
| Visibility/layout toggles | Tailwind `dark:` classes (`dark:hidden`, `hidden dark:block`)   |
| JS theme detection        | **Never.** No reading `document.documentElement` in components. |

### 3.6 Mintlify Override Registry

Overrides in `style.css` are documented technical debt. Each entry tracks: what's overridden, which Mintlify limitation necessitates it, introduction date, review date, owner, status. Reviewed quarterly against Mintlify release notes.

<CustomDivider />

## 4. Component Development Standards

### 4.1 Props Conventions (7 Rules)

1. **camelCase** prop names
2. **`is`/`has` prefix** for booleans (`isCompact`, `hasIcon`)
3. **`on` prefix** for handlers (`onClick`, `onToggle`)
4. **Defaults in destructuring** (`({ variant = 'default' }) => ...`)
5. **`children` for slot content, named props for data**
6. **Spread last** (`<div className={...} {...rest}>`)
7. **Required props: no default. Optional: always have default.**

### 4.2 Composition

**Inter-component imports are permitted via absolute `/snippets/` paths.** The importing component handles its own dependencies – the consuming MDX page does not need to re-import sub-components used internally by a component. Circular imports are not allowed.

Same-file references are also allowed (co-located components share scope).

### 4.3 Accessibility

**All components:** Semantic HTML, alt text on images, heading hierarchy, descriptive link text.

**Interactive components** (SearchTable, CardCarousel, ShowcaseCards, CopyText, DownloadButton, ScrollBox): additionally require ARIA roles/attributes, keyboard operability (Tab, Enter/Space, Escape), and visible focus indicators.

### 4.4 Error Handling (Mandatory)

Mintlify has no error boundary per component. **A component crash kills the entire page.** Defensive rendering is non-negotiable.

| Rule                        | Implementation                            |
| --------------------------- | ----------------------------------------- |
| Null-safe prop access       | Optional chaining, default values         |
| Guard required props        | Return `null` + `console.warn` if missing |
| Guard arrays                | `(items ?? []).map(...)`                  |
| Try-catch complex logic     | Wrap computed values, data transforms     |
| Console.warn on degradation | `console.warn('[ComponentName] reason')`  |
| Never throw                 | Catch internally, degrade gracefully      |

**MDX-facing component rule:** if a `.jsx` file is imported directly by a routable MDX page, exported components in that file must not rely on private file-scope helpers. Keep defensive logic inline in the exported component or import it from a colocated non-component `.js` helper module. Do not hoist the logic into top-level private locals inside the `.jsx` file.

### 4.5 Testing (Three Tiers)

| Tier                | What                                   | How                                     | Required for        |
| ------------------- | -------------------------------------- | --------------------------------------- | ------------------- |
| Visual verification | Light + dark mode rendering            | Manual, `mintlify dev`                  | All components      |
| Browser tests       | Page renders without error             | CI, existing infrastructure             | All used components |
| Unit tests          | Props, edge cases, defensive rendering | CI, `operations/tests/unit/components/` | All components      |

**Core unit test cases (every component):** renders with valid props, renders with no props, handles null/undefined data, handles missing required props, handles invalid prop types.

<CustomDivider />

## 5. Documentation & Example Standards

### 5.1 JSDoc Template

Every exported component carries this block:

```jsx icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
/**
 * @component ComponentName
 * @category elements
 * @subcategory icons
 * @status stable
 * @description One-line purpose statement.
 *
 * @param {string} [variant='default'] - Visual variant. One of: 'default', 'compact'.
 * @param {boolean} [isCompact=false] - Compact rendering mode.
 *
 * @example
 * <ComponentName />
 * <ComponentName variant="compact" />
 */
```

`@dataSource` is additionally required for all components in `integrators/`. All other governance fields are required for every export.

### 5.2 Metadata Schema (6 Fields + 1 Conditional, Enforced)

| # | Tag                  | Type   | Values                                                                                                                                                     |
| - | -------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1 | `@component`         | string | PascalCase export name                                                                                                                                     |
| 2 | `@category`          | enum   | `elements` · `wrappers` · `displays` · `scaffolding` · `integrators` · `config`                                                                            |
| 3 | `@subcategory`       | string | Sub-folder name within the category                                                                                                                        |
| 4 | `@status`            | enum   | `stable` · `experimental` · `deprecated` · `broken` · `placeholder`                                                                                        |
| 5 | `@description`       | string | One-line purpose                                                                                                                                           |
| 6 | `@dataSource`        | string | External pipeline/API (integrators only; `none` for others)                                                                                                |
| 7 | `@aiDiscoverability` | enum   | `snapshot` · `props-extracted` · `none` – **required on any hook-using component** (`useState`, `useEffect`, etc.); omit on pure/presentational components |

`@aiDiscoverability` declares whether a component hides content from crawlers and AI pipelines at runtime, and where its static companion file lives:

* `snapshot` → external-fetch component; companion at `snippets/data/snapshots/[source-id].json` (CI-regenerated)
* `props-extracted` → interactive/paginated UI; companion at `v2/[section]/[page-slug]-data.json` (author obligation, adjacent to MDX)
* `none` → hooks used for UI state only; no content hidden; no companion needed

### 5.3 Props Table Format (Published Docs)

| Prop   | Type     | Default      | Required | Description     |
| ------ | -------- | ------------ | -------- | --------------- |
| `href` | `string` | –            | Yes      | Destination URL |
| `icon` | `string` | `'livepeer'` | No       | Brand icon      |

Generated from `@param` tags. Five columns.

### 5.4 Examples

One rendered MDX example per exported component in `{category}/examples/{file}-examples.mdx`. Copy-paste ready with import statement. Required for `stable` components only.

### 5.5 Published Docs Generation

Fully automated. Zero human maintenance.

1. Registry generation (pre-commit): JSDoc → `component-registry.json`
2. Docs generation (manual/chained): registry + `@param` + `@example` + OpenRouter LLM → published MDX pages
3. LLM failure fallback: template-generated prose from metadata (deterministic)

### 5.6 Deprecation

```jsx icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
/**
 * @status deprecated
 * @deprecated Use GotoCard instead. Scheduled for removal Q3 2026.
 * @see GotoCard
 */
```

Published docs show deprecation banner. Component section moved to bottom of category page.

<CustomDivider />

## 6. Lifecycle & Governance

### 6.1 Lifecycle States

| State          | Meaning                                       | Badge  |
| -------------- | --------------------------------------------- | ------ |
| `stable`       | Production-ready, tested, documented          | Green  |
| `experimental` | Usable, API may change                        | Yellow |
| `deprecated`   | Scheduled for removal, replacement identified | Red    |
| `broken`       | Known defect, do not use                      | Red    |
| `placeholder`  | Stub/empty, not functional                    | Grey   |

### 6.2 Transitions

Free transitions – any state to any state. Update `@status` in JSDoc. Document reason in commit message. Registry captures the change automatically.

### 6.3 Governance Taxonomy

Category-level. One governance label per folder.

The current metadata field is `owner`, but it is taxonomy, not reviewer assignment or gatekeeper authority. Historical GitHub review maps may remain archived for reference, but tests, generated registries, and repair commands are the active contract.

### 6.4 Modification Rules

No immutability rule. Automated validation and the existing test infrastructure (58-script suite, 17 CI workflows, pre-commit hooks, browser tests) are the gates. Human review is collaborative, not ownership-based.

### 6.5 Deprecation & Removal

Usage-gated. A deprecated component is removed only when `@usedIn` is empty – no pages reference it. The registry tracks consumers. Published docs surface remaining consumers as migration prompts.

<CustomDivider />

## 7. Enforcement Summary

What's enforced, where, and how.

| What                                         | Enforced by                                                       | Blocks commit? |
| -------------------------------------------- | ----------------------------------------------------------------- | -------------- |
| 6 JSDoc governance fields present            | Pre-commit validation (`generate-component-registry.js --strict`) | Yes            |
| `@param` coverage matches props              | Pre-commit validation                                             | Yes            |
| `@category` matches folder                   | Pre-commit validation                                             | Yes            |
| `@status` is valid enum                      | Pre-commit validation                                             | Yes            |
| `@deprecated` present when status=deprecated | Pre-commit validation                                             | Yes            |
| No ThemeData                                 | Pre-commit regex scan                                             | Yes            |
| No hardcoded hex/rgb                         | Pre-commit regex scan                                             | Yes            |
| No `!important`                              | Pre-commit regex scan                                             | Yes            |
| Registry regeneration                        | Pre-commit auto-generation                                        | Auto-staged    |
| Static inline styles                         | Copilot code review                                               | No (advisory)  |
| Mintlify class overrides                     | Copilot code review                                               | No (advisory)  |
| Props conventions                            | Code review (human + Copilot)                                     | No             |
| Accessibility (ARIA)                         | Code review + unit tests                                          | Partially      |
| Defensive rendering                          | Unit tests                                                        | Yes (CI)       |
| Page-level rendering                         | Browser tests                                                     | Yes (CI)       |
| Visual light/dark mode                       | Manual verification                                               | No             |

<CustomDivider />

## 8. Generation Pipeline

### 8.1 Registry Generation

```icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
Trigger:  pre-commit (staged files in snippets/components/)
Script:   operations/scripts/generators/components/library/generate-component-registry.js
Input:    all JSDoc blocks in snippets/components/**/*.jsx
Output:   docs-guide/config/component-registry.json (auto-staged)
Errors:   missing/invalid fields → commit blocked
```

### 8.2 Published Docs Generation

```icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
Trigger:  manual or chained after registry update
Script:   operations/scripts/generators/components/documentation/generate-component-docs.js
Input:    registry + @param + @example + examples/ MDX files
Process:  OpenRouter LLM for editorial prose, template fallback on failure
Output:   7 published MDX pages per locale (overview + per-category) across 4 locales
Caching:  LLM output cached per component hash
```

<CustomDivider />

## 9. Decision Register (All 33 Decisions)

### D1: Classification & Purpose Model

| #  | Decision            | Choice                                                              |
| -- | ------------------- | ------------------------------------------------------------------- |
| 1  | Category taxonomy   | Six: Elements, Wrappers, Displays, Scaffolding, Integrators, Config |
| 2  | Compositional model | Metadata only – sub-niche folders, no compositional tier tag        |
| 3a | Metadata location   | JSDoc block in each JSX file                                        |
| 3b | Metadata schema     | 6 enforced fields (down from aspirational 14)                       |
| 4  | Decision mechanism  | Decision tree – ordered yes/no, first match wins                    |
| 5  | Library boundary    | `snippets/components/` only                                         |

### D2: Repo Structure & Documentation Architecture

| # | Decision            | Choice                                                           |
| - | ------------------- | ---------------------------------------------------------------- |
| 1 | Naming conventions  | camelCase files, PascalCase exports                              |
| 2 | File granularity    | Grouped files with per-export JSDoc                              |
| 3 | Canonical docs home | Hybrid – JSDoc SOT for metadata, published MDX SOT for editorial |
| 4 | Registry format     | Single JSON at `docs-guide/config/component-registry.json`       |
| 5 | Generation pipeline | Pre-commit hook auto-regeneration                                |
| 6 | Examples convention | Co-located `examples/` per category                              |
| 7 | Import paths        | Full explicit paths (Mintlify constraint)                        |

### D3: Styling Architecture & Standards

| # | Decision                 | Choice                                                    |
| - | ------------------------ | --------------------------------------------------------- |
| 1 | Style system authority   | Layered – components may define scoped vars if documented |
| 2 | Forbidden patterns       | Strict ban (3) + advisory (2)                             |
| 3 | Dark/light mode          | CSS tokens + Tailwind `dark:` utility                     |
| 4 | Inline styles            | Advisory flag sufficient                                  |
| 5 | Design tokens            | Rationalise and document with `--lp-*` namespace          |
| 6 | Mintlify override policy | Override registry – documented, justified, review-dated   |

### D4: Component Development Standards

| # | Decision          | Choice                                                                       |
| - | ----------------- | ---------------------------------------------------------------------------- |
| 1 | Props conventions | Standard 7 rules                                                             |
| 2 | Composition       | Inter-component imports via absolute `/snippets/` paths; no circular imports |
| 3 | Accessibility     | Semantic HTML + ARIA for interactive components                              |
| 4 | Error handling    | Defensive rendering mandatory – page crash prevention                        |
| 5 | Testing           | Visual + browser + unit tests (three tiers)                                  |

### D5: Documentation & Example Standards

| # | Decision             | Choice                                                           |
| - | -------------------- | ---------------------------------------------------------------- |
| 1 | JSDoc scope          | 6 governance fields + `@param` + `@example`                      |
| 2 | Props table format   | Standard 5-column                                                |
| 3 | Example requirements | Minimal – one per component, copy-paste ready                    |
| 4 | Published docs       | LLM-generated (OpenRouter) + template fallback, zero maintenance |
| 5 | Deprecation docs     | `@deprecated` + `@see` pointer                                   |

### D6: Lifecycle & Governance Model

| # | Decision            | Choice                                                        |
| - | ------------------- | ------------------------------------------------------------- |
| 1 | Lifecycle states    | Five: stable, experimental, deprecated, broken, placeholder   |
| 2 | Transitions         | Free – any to any, documented in commit                       |
| 3 | Governance taxonomy | Category-level metadata; reviewer routing is not the contract |
| 4 | Immutability        | No rule – code review + tests are the gate                    |
| 5 | Deprecation process | Usage-gated removal – only when @usedIn is empty              |

<CustomDivider />

## 10. Upstream Dependencies

This framework consumes but does not redefine:

| Document                     | What it provides                                                                       |
| ---------------------------- | -------------------------------------------------------------------------------------- |
| Page Taxonomy (SOT-00)       | 10 page types – components map via `@contentAffinity`                                  |
| Content Taxonomy             | Structural patterns per page type – components are the rendering layer                 |
| Composable Content Structure | Four reuse patterns – this framework governs UI components only                        |
| Mintlify Considerations      | Platform constraints: `/snippets/` paths, absolute import paths, arrow function syntax |

<CustomDivider />

## 11. Completed Work (D8 + D9)

The following were open items at framework inception and are now complete as of 2026-03-20:

* ✅ All components classified and migrated to new taxonomy (elements/wrappers/displays/scaffolding/integrators/config)
* ✅ All JSDoc governance fields populated on every governed export (6-field schema enforced by `--strict`)
* ✅ `generate-component-registry.js` operational – generates `docs-guide/config/component-registry.json`
* ✅ `generate-component-docs.js` operational – generates published MDX pages per locale
* ✅ Pre-commit hook enforces JSDoc fields and auto-stages registry
* ✅ Published component library pages regenerated for all 4 locales
* ✅ Import paths updated across all MDX pages after folder restructure
* ✅ ThemeData removed from all components
* ✅ Duplicate components resolved and archived

**Remaining (deferred to CONTENT-STRUCTURE Phase 5.1):**

* `component-layout-decisions.mdx` update – see [Section 12.3](#123-contentaffinity) below; unblocked as of 2026-03-21

<CustomDivider />

## 12. Composable Content Layer

### 12.1 Three-Layer Architecture

Components (`snippets/components/`) are the middle layer of a three-layer content architecture:

| Layer           | Location                                               | What it is                             | Governed by                  |
| --------------- | ------------------------------------------------------ | -------------------------------------- | ---------------------------- |
| **Data**        | `snippets/data/`, `v2/[section]/[page-slug]-data.json` | Structured data consumed by components | AI Discoverability framework |
| **Components**  | `snippets/components/`                                 | JSX rendering units                    | This document                |
| **Composables** | `snippets/composables/`                                | Portable MDX section blocks            | Composable Content Structure |

**Platform constraint (Decision D4):** JSX inter-component imports are permitted via absolute `/snippets/` paths, but circular imports are not allowed. Composables are `.mdx` files because they compose multiple components with authored prose. MDX can freely import JSX components; JSX can import other JSX via absolute paths.

### 12.2 Composable Section Library

As of 2026-03-21, `snippets/composables/` contains 8 composable section blocks:

| Composable                              | Tier | Page types                          |
| --------------------------------------- | ---- | ----------------------------------- |
| `related-resources-section.mdx`         | 1    | All – mandatory footer              |
| `steps-section.mdx`                     | 1    | instruction, tutorial, start, build |
| `prerequisites-section.mdx`             | 1    | instruction, tutorial, start        |
| `accordion-faq-section.mdx`             | 1    | reference (compendium), concept     |
| `accordion-glossary-section.mdx`        | 1    | reference (compendium), concept     |
| `accordion-troubleshooting-section.mdx` | 1    | reference (compendium), instruction |
| `overview-intro-section.mdx`            | 2    | All – optional opening block        |
| `validation-section.mdx`                | 2    | instruction, tutorial, start        |

Each composable includes a `@composable` governance header (purpose, pageTypes, variables, notes) and uses `{/* */}` comments to show optional sub-elements inline at point of use.

**Lifecycle rule:** Content starts local to a page. Promote to `snippets/composables/` only when a concrete second consumer appears.

### 12.3 @contentAffinity

`@contentAffinity` is a deferred JSDoc field (field #8 on the aspirational schema, deferred in prior sessions) that declares which page types a component is appropriate for.

**Status:** Not yet enforced. Page taxonomy is now locked (15 `purpose` values, 10 `pageType` values), making this field unblocked.

**Proposed syntax:**

```jsx icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
/**
 * @contentAffinity  start, build, instruction
 */
export const StepsWizard = () => ...
```

**When to add it:** When a component's appropriate page types are non-obvious from its name and category. Not required on universal components (CustomDivider, CardGroup equivalents). Required on scaffolding/, integrators/, and page-specific displays/.

**Enforcement:** Add to `--strict` mode in `generate-component-registry.js` as part of CONTENT-STRUCTURE Phase 5.1.
