---
title: "Components"
description: "Every component opsinjs has specified, with the status of each, listed in one table so nobody has to guess whether something exists."
url: "https://opsinjs.pensievelabs.org/components"
source: "https://opsinjs.pensievelabs.org/components.md"
section: "Components"
kind: "reference"
---

> Elements written as `<PascalCase … />` below are opsinjs documentation
> components. Their attributes are the content: the values they render are
> generated from `tokens/*.json` and `registry/catalogue.ts` and are
> published separately at https://opsinjs.pensievelabs.org/r/index.json and under the Reference
> section.
> Nothing is missing from this page. The data simply does not live in
> the prose.

<PageTemplate kind="reference" />

**Every component in the catalogue is implemented and installable.** Each has a
file under `registry/bases/base/`, a registry item the shadcn CLI copies into a project,
and a page that documents the cases it refuses as carefully as the ones it serves. Every
one is `shipped`, and no further: none has been through an independent
accessibility or clinical review, none is ready for a production health surface, and each
page lists what has not been measured rather than implying it has been. That status is on
every component page in prose and in machine-readable form, at a URL you can guess
from the component name.

That is what this page is for. The failure it exists to prevent is an agent, or a
developer in a hurry, inferring an API from a plausible name and shipping it into a
product that shows people their own health data. A definitive answer at a guessable URL
is worth more than a 404, and far more than an invented answer.

<SectionProgress />

Every id in the catalogue has code, a registry item and a hand-written page. Filter by
category or status, or search the synonyms: `normal range`, `kpi`, `gauge`, `not medical
advice`, `ago`.

<StatusMatrix />

**Status is a promise about change, not a quality score.** `shipped` means the code
exists and is documented, and the API may move in any release. It says nothing about
whether anybody has reviewed it, and nobody has.
[Release phases](../project/release-phases.mdx) sets out what the three phases promise
about semver, the page's own outline and the registry.

**Category does two jobs.** It groups the sidebar, and it is load-bearing: any category
beginning with `health-` makes the **Clinical meaning** section and the `governedBy`
frontmatter mandatory, and the build fails without them. It makes their absence mandatory
elsewhere too, so [Button](./button.mdx) cannot acquire a clinical meaning by accident.

**Aliases are search synonyms**, unique across the whole corpus, because the person
searching does not know our vocabulary. Someone typing *normal range* wants
[RangeBar](./range-bar.mdx), and the first thing that page tells them is that
[normal is a banned word](../health/reference-ranges.mdx), and why.

**Governed by links a component to the doctrine that constrains it.** Doctrine is written
once in [Health](../health/index.mdx) and referenced from every component that must obey
it, in both directions, so a rule cannot quietly end up applying to nothing.

If you are choosing a component, the decision table in
[Choose a component](../recipes/choose-a-component.mdx) maps the shape of your data to the
component that displays it. Reading that table is faster than reading every page.
If you are writing or reviewing one of these pages, read
[Anatomy of a component page](./anatomy-of-a-component-page.mdx); it publishes the
page contract once so you fill in a template instead of inventing a structure. If
you are here to judge whether opsinjs is worth building on, read
[RangeBar](./range-bar.mdx): it carries the most detailed clinical contract in the set and
it is the component the rest of the system is arranged around.

## How this is generated [#how-this-is-generated]

The table above is not hand-maintained. Every row comes from `registry/catalogue.ts`,
the single declaration of every component id, its category, its status and its alias
namespace. `scripts/build-registry.mts` reads it and writes `lib/generated/catalogue.json`
and `public/r/index.json`; `<StatusMatrix>` renders that JSON and `<SectionProgress>`
counts it.

Nothing here is typed twice. If a row is wrong the catalogue is wrong, and editing this
page cannot fix it. `scripts/assert-ia.mts` fails the build when a catalogue id is missing
the page it should have, when a page claims an id the catalogue does not know, or when two
pages claim the same alias.
