Skip to content

Write your first glossary

You write one glossary for the bounded context billing. It holds two terms of the billing language, in German and in English.

You need a text editor and a folder in your project. A glossary is plain YAML, so you need no tool to write it.

Create a file named billing.glossary.yaml.

Write these four lines into the file.

boundedContext: billing
titles:
- {language: de, text: Abrechnung}
- {language: en, text: Billing}
concepts: []

The field boundedContext is the sole key of the glossary. The path of the file carries no meaning, so the file can sit anywhere in or outside your repository.

The field titles names the glossary once per language. The field concepts is empty for now.

Your file is now a glossary of one bounded context with no terms in it.

Replace the line concepts: [] with these lines.

concepts:
- id: invoice
prefLabels:
- {language: de, text: Rechnung}
- {language: en, text: Invoice}
altLabels: []
hiddenLabels: []
definitions:
- {language: de, text: Die Zahlungsaufforderung an den Kunden nach Lieferung.}
- {language: en, text: The request for payment sent to the customer after delivery.}

The field id is the key of the term inside this glossary. It is kebab-case, and no second term of this glossary carries it.

A term has exactly one preferred label per language. Rechnung is the German word for this term, and Invoice is the English word for it.

A term carries at least one definition. The lists altLabels and hiddenLabels stay empty until you fill them.

Your file now holds one term with two words and two definitions.

Step 3. Give the term a status, an origin, and a kind

Section titled “Step 3. Give the term a status, an origin, and a kind”

Add these three lines under the definitions of invoice.

status: confirmed
origin: owner
kind: entity

The field status says how far the term is settled. Its four values are confirmed, unconfirmed, proposed and deprecated. The billing team settled this term, so the value is confirmed.

The field origin says who put the word into circulation. Its three values are owner, standard and llm. A domain expert on your own team named this term, so the value is owner.

The field kind says what the term names in the model. Its seven values are entity, event, field, role, actor, value and rule. An invoice is a thing with an identity, so the value is entity.

A reader of your file can now tell a settled term from a proposal.

Add these two lines under kind.

grounding: ['code:Invoice']
related: []

The field grounding lists the places that use the term. An entry is a path with an anchor, a code element, or an element of your model.

The field related holds terms of this same glossary that stand next to this one. It stays empty until step 6.

A reader who looks the term up now sees where the model uses the word.

Step 5. Add the second term and the word you rejected

Section titled “Step 5. Add the second term and the word you rejected”

Add these lines under the first term, at the same indentation as - id: invoice.

- id: mehrwertsteuer
prefLabels:
- {language: de, text: Mehrwertsteuer}
altLabels: []
hiddenLabels:
- language: en
text: VAT
reason: British VAT follows a different law. The translation hides that.
rejectedOn: '2026-09-08'
definitions:
- {language: de, text: Die Steuer nach deutschem Umsatzsteuergesetz, die auf der Rechnung ausgewiesen wird.}
scopeNote: Bleibt in Code und Dokumenten unübersetzt.
status: confirmed
origin: standard
standardRef: UStG
kind: value
grounding: ['code:Mehrwertsteuer']
related: []

This term has one preferred label, because the team keeps the German word in every language.

The list hiddenLabels holds the English word VAT. Each hidden label carries the reason for the rejection and the date of the rejection.

The value standard in origin says that a standard coined the word. The field standardRef then names that standard, here the German UStG.

A search for VAT now leads a reader to this term and to the reason against the word.

Replace related: [] of the term invoice with this line.

related: [mehrwertsteuer]

Replace related: [] of the term mehrwertsteuer with this line.

related: [invoice]

The field related joins two terms of one glossary. Both entries are ids of terms in this same file.

A reader who looks up the invoice now finds the tax term next to it.

A document is conformant when it passes the JSON Schema of the format and satisfies every invariant of the specification. The reference implementation is the package ubilang, in the repository under apps/ubilang. The name of the published command is not fixed yet.

Read your file against the invariants that apply to it.

  • AConceptHasOnePreferredLabelPerLanguage. Each of your two terms carries one German word, and invoice carries one English word.
  • AConceptCarriesADefinition. Each of your two terms carries at least one definition.
  • PreferredLabelsAreUniqueWithinAScheme. Rechnung and Mehrwertsteuer are two different words in one glossary.
  • ConceptIdsAreUniqueWithinAScheme. The ids invoice and mehrwertsteuer differ.
  • AHiddenLabelCarriesAReason. The rejected word VAT carries its reason.
  • AStandardTermNamesItsStandard. The term with origin: standard names UStG in standardRef.
  • RelatedStaysWithinOneScheme. Both entries of related are terms of this glossary.

Your glossary satisfies every one of them.

The file billing.glossary.yaml is the glossary of the bounded context billing. It holds two terms in two languages. Each term carries a definition, a status, an origin, a kind, and a ground in the code. One rejected English word stays in the file with the reason against it.

For a single next goal, read the guide on a rejected word, on a term across two contexts, or on a glossary from another repository.

Written and maintained by Tobias Brennecke.tobiasbrennecke.com