opsinjs
RoadmapDecisions

Decisions

Architecture decision records say why the system is shaped the way it is, including the choices that constrain everything built after them.

What these are

An architecture decision record is one page describing one decision: what forced it, what was chosen, what was rejected, and what the project accepted as a consequence. They are numbered, they are never rewritten to look better in hindsight, and they are public.

They are public because of who is expected to depend on this system. A team adopting a component library for a patient-facing product may have to justify that choice to a clinical safety officer, an accessibility auditor or a procurement reviewer, none of whom were in the room. "The system does it this way" is not an answer to any of them. A dated record naming the alternative and the trade-off is.

The format

Every record has the same six headings, and the two that matter most are the two usually missing.

Consequences is where the cost is written down. A decision with only benefits listed has not been thought about; it has been advertised. Consequences include the things that got harder, the work the decision created, and the risks accepted.

Alternatives considered names the option that was rejected and why. This is what makes a record useful in two years, when somebody proposes the rejected option again. They usually have good reasons, because the reason it was rejected may have expired.

Status values

StatusMeaning
ProposedWritten, not yet agreed
AcceptedIn force. The system is built this way
Accepted, not yet implementedAgreed and binding, but the code is not written
SupersededReplaced by a later record, which is named. The page stays

A record is normally kept even after it is reversed, because the reasoning that produced a decision we later undid is the most useful thing in this folder. The exception is a record whose subject no longer exists in the system at all. Two records described the considered release phase and the roster built from it. That phase has been removed from the vocabulary, so those records described a mechanism that no page, no script and no catalogue row can refer to any more, and a page kept on the site keeps teaching its vocabulary to every reader and to every agent fetching the .md twins. A reader cannot tell a withdrawn record from a live one by reading it, which is why the page goes rather than gaining a banner. They were withdrawn and deleted, and 0023 names what went. Three conditions hold whenever that happens: the record that removes the mechanism names what went, the number is never reused, and git history is the archive.

When to write one

Write a record when a choice is expensive to reverse, constrains work that comes after it, or will look arbitrary to somebody who arrives later. Choosing a primitive library, a distribution model or a colour architecture qualifies. Choosing a variable name does not.

Write it before implementing, not after. A record written afterwards describes what happened; a record written first is a decision that can still be argued with while arguing is cheap.

The records

#DecisionStatus
0001Base UI, not Radix, as the primitive layerAccepted
0002Distribute as a shadcn registry; no CLI firstAccepted
0003Two independent colour axes that never mixAccepted
0004lyra themes the documentation chrome onlyAccepted
0005No [lang] segment; bound the retrofit insteadAccepted
0006Source, tables and measured numbers are generatedAccepted
0007Two sibling root layouts, and no app/layout.tsxAccepted
0009The default export of a registry file is a zero-prop demoAccepted
0010Shared code ships inside every registry itemAccepted
0011Anatomy parts are internal structure, identified by data-slotAccepted
0012Example data is synthetic and explicitly unsourcedAccepted
0013A component preview is an iframe, not an inline renderAccepted
0014The material rung names are the token namesAccepted
0015One flat error-code scheme; errors.json is the sourceAccepted
0016The unit table ships spoken forms, not conversion factorsAccepted
0017precision means decimal places, everywhereAccepted
0021A modal surface owns its own open stateAccepted
0023Three release phases, and only a component page carries oneAccepted, outline superseded by 0024
0024The component page is leanAccepted
0025The WCAG 2.2 AA audit is author-run, not an independent reviewAccepted

The numbers are not contiguous. There is no 0008, no 0018 to 0020 and no 0022. 0008 and 0022 were withdrawn and deleted; 0018 to 0020 were never written. The gaps are in the numbering rather than in this table, and they are left as they are because renumbering a record would break every link and every citation that already names it.

Edit this page

Last read through against the system on 2026-09-02. Due for review every 12 months; expiry is reported by pnpm run check:freshness.

On this page