---
title: "Glossary"
description: "The A to Z as data. The record shape, how Term resolves an entry, how to propose one, and where the machine-readable copy lives."
url: "https://opsinjs.pensievelabs.org/content/glossary"
source: "https://opsinjs.pensievelabs.org/content/glossary.md"
section: "Content & language"
kind: "content"
reviewed: "2026-09-20"
reviewer: "content"
aliases: ["term definitions", "word list", "glossary data"]
---

> 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="content" />

## The rule [#the-rule]

**One vocabulary, one file, many surfaces.** The plain-English vocabulary is
authored once in `tokens/glossary.json` and consumed everywhere: by `Term` in a
running product, by the filterable A to Z on
[Plain-English A to Z](./plain-english-a-z.mdx), by the generated
[glossary reference](../reference/generated/glossary.mdx), by search, and by the
machine-readable output at `/r` that an agent reads.

This page is about the vocabulary as *data*.
[Plain-English A to Z](./plain-english-a-z.mdx) is canonical for the *rule*.
That page says how a replacement word is chosen and why. The two do not restate
each other, and `assert-ia.mts` checks that they do not.

### Why it is data and not prose [#why-it-is-data-and-not-prose]

Three reasons, and the third is the one that decided it.

* **Consistency is mechanical.** A writer cannot remember whether the product
  says "usual range" or "typical range". A lookup can.
* **It is checkable.** A term used in a component's copy that is not in the file
  is a build-time question, not a review-time argument.
* **Agents need it.** An agent generating a health screen will otherwise invent
  plain-English wording, and the wording it invents will be plausible, fluent and
  subtly clinical. Publishing the vocabulary as JSON turns that from a
  generation problem into a lookup.

### The record shape [#the-record-shape]

Each entry is one clinical term. The fields:

| Field        | Required | What it is                                                                                                 |
| ------------ | -------- | ---------------------------------------------------------------------------------------------------------- |
| `term`       | yes      | The clinical term, as the reader will meet it on a document. Its natural case, so "HbA1c", not "hba1c".    |
| `plain`      | yes      | The replacement phrase. Two or three words. Used verbatim in copy.                                         |
| `definition` | yes      | One original sentence, written for a lay reader. Never copied from a clinical source.                      |
| `seenOn`     | no       | Where the reader is likely to meet the clinical term, such as a prescription, a results letter, a monitor. |
| `aliases`    | no       | Search synonyms and common misspellings.                                                                   |
| `category`   | no       | The health category the term belongs to, from the category axis.                                           |

Two rules about the fields. `plain` is a phrase the product will actually print,
so it must read correctly mid-sentence. That means lower case unless it is a
proper noun, and no trailing full stop. `definition` is one sentence, not a
paragraph, because it is rendered inside a popover next to a word.

## Approved / Rejected [#approved--rejected]

<DoDont>
  <DoDont.Do>
    plain: "high blood pressure" with definition: "Blood pressure that stays higher than the usual range over time, rather than on a single reading."
  </DoDont.Do>

  <DoDont.Dont>
    plain: "hypertension" with definition: "A chronic medical condition characterised by persistently elevated arterial blood pressure."
  </DoDont.Dont>
</DoDont>

The rejected record does both of the things this file exists to prevent: the
replacement is the clinical term unchanged, and the definition is written in the
register the vocabulary is supposed to translate out of. It also uses "chronic"
in the definition of a term whose own entry would replace "chronic".

<DoDont>
  <DoDont.Do>
    plain: "average blood sugar" with seenOn: "your results letter and your GP's records"
  </DoDont.Do>

  <DoDont.Dont>
    plain: "sugar level" with no seenOn, and the term written in lower case
  </DoDont.Dont>
</DoDont>

The second rejection is subtler. "Sugar level" is plainer and it is wrong: it
describes a different measurement from the one the term names, and without
`seenOn` the reader has no way to connect the phrase in the app to the code on
the letter in their hand.

A complete record, as it appears in the file:

```json
{
  "term": "HbA1c",
  "plain": "average blood sugar",
  "definition": "A blood test that shows the average amount of sugar in your blood over the past two to three months.",
  "seenOn": "your results letter and your GP's records",
  "aliases": ["a1c", "glycated haemoglobin", "haemoglobin a1c"],
  "category": "metabolic"
}
```

## Patterns [#patterns]

**Adding an entry.** The definition is the hard part. Write it in this order and
the register usually takes care of itself:

<Steps>
  ### Say what it is, in one clause [#say-what-it-is-in-one-clause]

  Start with "a", "the" or a verb. Never with the clinical term repeated.

  ### Say what it means for the reader [#say-what-it-means-for-the-reader]

  The clause that answers "so what?". This is the clause that clinical sources omit
  and lay readers need.

  ### Stop [#stop]

  One sentence. If you need a second, the extra material belongs on a page, and the
  entry should link to it rather than grow.
</Steps>

**Proposing an entry you cannot write.** If you know a term needs an entry but
cannot write the definition, open it as a proposal rather than adding a weak one;
a bad definition is worse than a missing one, because `Term` will render it
confidently. See [Proposing a
component](../handbook/contributing/proposing-a-component.mdx).

**Challenging an entry.** Entries are versioned with everything else, and a
change to `plain` is a change to strings a product is printing. Treat it as a
breaking change to copy and record it in the changelog.

### The rendered list [#the-rendered-list]

The full filterable list is rendered on
[Plain-English A to Z](./plain-english-a-z.mdx), which is the page to send a
writer to. The generated, machine-readable form is at
[the glossary reference](../reference/generated/glossary.mdx).

<NoDataYet script="scripts/build-tokens.mts" />

## Banned words [#banned-words]

Banned in `definition` text specifically. These are the words that leak the
clinical register back into the file that exists to remove it.

| Banned in a definition             | Why                                                   | Use instead                                          |
| ---------------------------------- | ----------------------------------------------------- | ---------------------------------------------------- |
| characterised by, is defined as    | Dictionary register; nobody speaks like this.         | start with what it is                                |
| chronic                            | The word being defined, or one just like it.          | long-term                                            |
| elevated, decreased, deranged      | Clinical comparatives.                                | higher, lower                                        |
| patient                            | The reader is not a patient inside their own app.     | you, or people                                       |
| may be indicative of               | Hedged clinical inference.                            | can be a sign of                                     |
| pathology, aetiology, presentation | Register with no lay equivalent in context.           | rewrite the sentence                                 |
| refer to your physician            | Not the reader's word, and usually not their country. | contact your GP, or whatever your product's route is |

## Related components [#related-components]

* **`Term`** is the only consumer that resolves a record at runtime. It renders
  the clinical word with `plain` and `definition` available; a term with no
  record renders as plain text rather than inventing an explanation.
* **`Glossary`** is the filterable list component.
* **`CareCard`*&#x2A; and &#x2A;*`ConsentSheet`** are the two surfaces most likely to
  introduce a term the reader has never met, and therefore the two most dependent
  on this file being complete.
