Using the system
How to install it, how to theme it without breaking the parts that carry risk, and what you are still responsible for once you have. That last part is most of this page: a design system can carry design decisions into your product, but it cannot carry your regulatory obligations.
What this is
A copy-in component library and a set of foundations for software as a medical device,
built on shadcn/ui — Radix primitives,
Tailwind, cva variants. Components are copied into your repository rather than
installed as a dependency, which is deliberate: for a regulated product you need to read, pin
and version-control the source of anything that renders a clinical value.
Structurally informed by conventions proven at scale in enterprise clinical design systems, and aligned to IEC 60601-1-8 alarm priorities and WCAG 2.2 AA — with all contrast ratios computed and machine-verified in CI. Not clinically validated. Usability validation is device-specific and belongs in your IEC 62366-1 file. If you place a device on the market using this system, you carry the usability engineering and clinical evaluation obligations under the MDR or IVDR regardless of what you built the interface from — see Status & limitations and Validation roadmap.
Install
# Foundations first — the token layer everything else reads from.
$ npx shadcn@latest init
$ npx shadcn@latest add https://md.notjustany.tech/r/foundations.json
# Then components, individually. Nothing is bundled; you take what you use.
$ npx shadcn@latest add https://md.notjustany.tech/r/alert-banner.json
$ npx shadcn@latest add https://md.notjustany.tech/r/key-value.json
# The two gates. Run them in CI from the first commit, not the last.
$ npm run check
Installing foundations.json writes two things: the token contract in your global
stylesheet, and tokens.json — the single source of truth the gate checks the
stylesheet against. Keep both under version control. They are design-control records, not build
artefacts.
Theming, and what you may not theme
Tokens are split into two classes, and the split is enforced by
scripts/check-tokens.mjs rather than by convention. See
Tokens & governance for the full
contract.
| Class | Examples | You may |
|---|---|---|
| Open | --primary, --secondary, --accent,
--radius, --card |
Re-theme freely to your own brand, provided the contrast pairs still pass the gate. |
| Governed | --alarm-*, --input, --ring,
--destructive |
Change only with a documented risk assessment. These are controlled characteristics; the gate fails the build if they are redefined anywhere outside the two blessed blocks. |
- The alarm palette is identical in light and dark. IEC 60601-1-8 specifies hues in absolute terms, so theme parity is checked, not assumed.
--destructiveis not an alarm. It marks a destructive action. Using it for a clinical state, or an alarm hue for a delete button, both fail review.- Brand coral never appears in product UI. It measures ΔE 22.6 against
--alarm-critical, below the 25 separation threshold — see Colour. - Do not add a
var()fallback to paper over a missing token. A fallback hides exactly the drift the gate exists to catch.
Wiring the gates into CI
There are two, and they fail for different reasons. Both exit non-zero and both emit a JSON report that is retained as design-control evidence.
| Gate | Checks | Catches |
|---|---|---|
check:tokens |
parity · contrast · sync · redefinition · hue separation | A safety-relevant visual decision drifting — an alarm hue re-themed, a contrast pair dropping below its minimum, a governed token redefined in a skin. |
check:docs |
links · styles · fallbacks · skeleton · tables · claims · markup · structure · counts · apps | The documentation drifting away from what it documents — a cross-reference to a renamed section, a class the stylesheet no longer defines, an overstated validation claim, a page nobody can navigate to, a build-status figure that no longer matches what is on disk, or a product name that was never registered. |
# .github/workflows/design-system.yml — two independent jobs, so a broken
# cross-reference and a drifted token do not mask each other.
- name: Token governance
run: npm run check:tokens:json > token-governance-report.json
- name: Documentation integrity
run: npm run check:docs:json > docs-integrity-report.json
- uses: actions/upload-artifact@v4
with:
retention-days: 90
Treat a red gate the way you would treat a failing unit test on a safety function: fix the
cause, do not add an exemption. The one time the exemption is right — a governed token genuinely
must change — the change belongs in tokens.json with a rationale, and
that rationale is what your risk file cites.
Both gates have been negative-tested: violations of every class each script claims to detect were injected into a copy of this repository and confirmed to fail the build. A checker nobody has watched fail is not evidence that anything is being checked.
What stays yours
Adopting this system moves some design decisions off your plate. It moves none of your obligations. The division is deliberately blunt:
| The system provides | You still own |
|---|---|
| Alarm priority mapping aligned to IEC 60601-1-8 | Which of your conditions are critical, urgent or advisory — a clinical decision, documented in your risk file |
| Contrast ratios computed and verified in CI | Verification in your real use environment — ambient light, glare, gloves, screen class |
| Components with stated risk controls | The hazard analysis those controls are traced to (ISO 14971) |
| Patterns with stated intended users and goals | Your specified users, goals and context of use, and summative evaluation against them (IEC 62366-1) |
| Vocabulary from ISO 9241-11 for describing outcomes | The measurements. This system states attributes believed to contribute to an outcome; only observed use establishes the outcome |
| Accessible markup and keyboard models | An accessibility conformance statement for your shipped product |
Throughout this system, a mismatch between what a clinician did and what they intended is a use error, not a user error. The distinction is IEC 62366-1's and it is not pedantry: it points the corrective action at the interface, which is where you can actually change something.
Adopting incrementally
You do not have to take everything. In rough order of value if you are retrofitting an existing product:
- Tokens and the gate. Cheap, and it starts producing evidence immediately.
- Alert banner and status chip. These carry the alarm priority model, which is the part most often built inconsistently across a product.
- Key–value pair. The unit-binding and absence rules touch nearly every screen and catch a whole class of display error.
- Data grid, list and filter. The denominator rules — knowing what is not on screen.
- Everything else, as the screens that use them come up for work.
Mixing this system with your existing components is expected during a migration. Where they disagree visually, prefer consistency within a screen over consistency with the system — a screen that looks like two products is harder to read than a product that looks like two screens.
Do's and don'ts
Run npm run check in CI from the first
commit, and keep both JSON reports as artefacts.
Evidence is much cheaper to accumulate than to reconstruct. A 90-day history of passing gates is a design-control record; a green build today is not.
Add the gate late, then add exemptions to get it green.
Every exemption is a governed token someone changed without a rationale. That is the exact record an auditor will ask about.
Re-theme --primary, --accent
and --radius to your brand.
These are open tokens. The gate re-checks every contrast pair against your values, so brand and accessibility do not have to be argued about.
Re-theme --alarm-urgent to your brand
yellow because it is "close enough".
Close enough moves the hue away from the IEC 60601-1-8 convention a clinician has learned in every other device on the ward.
Cite the component pages' Clinical safety notes in your hazard analysis, then verify each control in your own product.
The controls are stated so they can be traced. Tracing them is your work; stating them is ours.
Cite this system as evidence that your interface is validated.
It is not, and the claim would not survive review. Usability validation is device-specific and belongs in your IEC 62366-1 file.
Pin a version and read the diff when you upgrade.
Copy-in distribution exists so that a change to a component that renders a clinical value is a reviewable change in your repository.
Track latest and let component source
update silently.
A silent change to alarm rendering is a change to a risk control that nobody assessed.
Getting help and reporting problems
- A component behaves unsafely — this is the highest-priority class of issue. See Contributing for what to include.
- A rule blocks a legitimate clinical workflow — say so. A rule that forces a workaround is a worse risk control than no rule, and several rules here exist in their current form because of exactly that feedback.
- The gate fails on a change you believe is correct — open it with the JSON report attached. The report names the failing pair and the measured value.
- Something is missing. Coverage and known gaps are listed on Status & limitations.
Related
- Status & limitations — what is built, what is not, and what this system does not claim.
- Validation roadmap — where the manufacturer's obligations begin.
- Contributing — how changes are proposed and reviewed.
- Tokens & governance — the full token contract and the five checks.
- Usability & context of use — the ISO 9241-11 vocabulary used throughout.