Skip to content
THOS

Built and operated by Laetoli (T) Limited in Dar es Salaam. A private system, built to national standards.

Language

Design system

The tokens and components all 16 products are built from, rendered by the code that ships, in both themes and both languages.

Paper and ink

The neutral ramp, twelve steps, authored in OKLCH so one step is the same perceptual distance everywhere. Warmth sits at hue 85° with chroma between 0.004 and 0.011: enough that a full screen reads as a printed page rather than a browser default, never enough to read as beige.

Light

  1. 0ground#fefdfc
  2. 1raised#f9f8f5
  3. 2sunken#eeedea
  4. 3fill#e3e2de
  5. 4hairline#d7d5d0
  6. 5border#bcbab6
  7. 6borderStrong#898783
  8. 7muted#6d6b66
  9. 8secondary#5a5853
  10. 9strong#3f3d38
  11. 10heading#262421
  12. 11ink#12100e

Dark

  1. 0ground#100f0c
  2. 1raised#191815
  3. 2sunken#262421
  4. 3fill#302d2a
  5. 4hairline#3c3a36
  6. 5border#514e4a
  7. 6borderStrong#716e6a
  8. 7muted#8e8b86
  9. 8secondary#a4a19d
  10. 9strong#c3c0bd
  11. 10heading#e0deda
  12. 11ink#f5f3f0

The institutional accent

The flag's green sits at step 5 at its published value. It is the identity anchor and is not adjusted. But against paper it reaches only 2.64:1, which fails AA for text at any size. The ramp holds the same hue, 145.09°, and walks lightness down until step 8 reaches 8.90:1 and clears AAA. That step is what carries interface emphasis.

  1. 1#edf8ec1.07:1 · fail
  2. 2#d6eed51.21:1 · fail
  3. 3#b1dfb11.48:1 · fail
  4. 4#7cc87f1.98:1 · fail
  5. 5#1eb53a2.68:1 · failFlag
  6. 6#12942c3.93:1 · AA-large
  7. 7#1271226.06:1 · AA
  8. 8#0f54199.03:1 · AAAWorking
  9. 9#07380e13.04:1 · AAA

Clinical semantics

Colour in the clinical application means clinical state and nothing else. Every state carries its non-colour differentiator, a glyph, a weight, a rule treatment and a name in both languages, as part of the token, so a component cannot paint the colour without also having the glyph and the label to hand.

Clinical state tokens
StateGlyphNameWeightRuleLightDark
critical‡Critical700double7.14:17.21:1
abnormal-high↑High600solid7.14:17.11:1
abnormal-low↓Low600solid7.09:17.19:1
normalnoneNormal400none18.70:117.33:1
pending·Pending400dashed6.69:16.91:1
corrected∆Corrected600double7.16:17.09:1
expired⁄Expired400hatched5.27:15.66:1
controlled◊Controlled600solid7.12:17.18:1
allergy†Allergy700solid7.15:17.19:1
stat!!STAT700double7.11:17.19:1

"Normal" is deliberately colourless. A colour that means "nothing is wrong" spends the reader's attention to say nothing: and that decision is what leaves the flag green free for institutional use. "Pending" and "expired" are held to AA rather than AAA: neither carries a live clinical value, and making absent data shout as loudly as a live abnormal result is a patient-safety regression in the opposite direction.

Typography

IBM Plex Sans, self-hosted, subset to 255 codepoints. Tabular figures are the global default. The serif is reserved for long-form policy and legal text and appears nowhere else.

  1. micro 12pxThe patient has arrived 0123456789
  2. compact 13pxThe patient has arrived 0123456789
  3. body 14pxThe patient has arrived 0123456789
  4. narrative 15pxThe patient has arrived 0123456789
  5. reading 16pxThe patient has arrived 0123456789
  6. lead 18pxThe patient has arrived 0123456789
  7. h4 21pxThe patient has arrived 0123456789
  8. h3 25pxThe patient has arrived 0123456789
  9. h2 30pxThe patient has arrived 0123456789
  10. h1 36pxThe patient has arrived 0123456789
  11. title 44pxThe patient has arrived 0123456789
  12. statement 56pxThe patient has arrived 0123456789

Space and structure

Space
8 · 16 · 24 · 32 · 40 · 48 · 64 · 80 · 96 · 128 · 4 · 12 pxAn 8px baseline, enforced
Radius
none 0px · sm 4px · md 8px · lg 12pxNo pill token. State is carried by word and rule, not by a chip
Border width
1pxOne only. Hierarchy comes from a rule's colour, never its weight
Elevation
3Three, for floating layers only. A resting surface has no shadow
Motion
120ms · 160ms · 200msOne curve, three durations, zeroed under prefers-reduced-motion
Measure
62–72chRunning prose never exceeds it

Components

Every component here runs on the same tokens and the same shipped typeface as production. Change the theme or the language at the top of the page and all of it changes with them.

DataTable

5 rows
Ward round worklist
TZ-04-118293Neema Juma MwakalingaKinondoniNHIF6.8mmol/LCritical2026-08-21
TZ-04-118294Hamisi Salum MohamedUbungoCHF4.1mmol/L2026-08-19
TZ-04-118295Asha Ramadhani KileoIlalaNHIF2.9mmol/LLow2026-08-24
TZ-04-118296Baraka Elias MchomeTemekePrivateNot recordedmmol/LPending2026-08-25
TZ-16-004871Zainabu Athumani KimaroNyamaganaiCHF5.1mmol/L2026-08-18

Ledger & ClinicalValue

Legal name
Neema Juma Mwakalinga
MRN
TZ-04-118293
Insurance
NHIF · 7391-4402-11Valid to 31/12/2026
Allergies
PenicillinAllergyRecorded 12/03/2024
Potassium
6.8mmol/LCriticalReference 3.5–5.1
Occupation
Not recorded
Next of kin
Not yet asked

Clinical states, inline

6.8mmol/LCritical5.4mmol/LHigh4.1mmol/L2.9mmol/LLow—Pending11.2g/dLCorrectedMorphine 10mg/mLControlledFBCSTAT

StatBlock

FHIR resource types published

18

CapabilityStatement

Connected facilities

Onboarding begins Q4 2026 with 12 pilot facilities in Dar es Salaam and Mwanza.

Facility registry

The first was measured: the mediator declares these types and the count is checkable. The second was never measured, so it says so in words instead of printing a zero. §4.6 leaves no middle path: where a figure is zero, print the roadmap state rather than the number.

Diagram

THOS federationHow a record moves between a facility, the core and a payer. Facility system → THOS core (HL7 v2 ADT). THOS core → THOS Labs (FHIR R4); Federation API (FHIR R4). THOS Labs. Federation API → NHIF (ISO 20022). NHIF.Facility systemGoTHOMIS, AfyaCareTHOS coreFHIR R4 canonicalTHOS LabsFederation APIOpenHIE mediatorNHIFHL7 v2 ADTFHIR R4FHIR R4ISO 20022

Fields

NEMLIT formulary. Level-of-care restrictions apply.

Appointment reminders are sent to this number.

Day before month.

Floating layers

Skeleton

Row heights match DataTable exactly, so the swap does not move the layout under a click already in flight.

Why there is no Card

There is no Card component in @thos/ui, deliberately. Cards flatten everything to the same weight: a grid of identical cards hides which item matters and destroys any order that carried meaning. Structure is chosen from the content rather than imposed on it, and the vocabulary is this:

  1. 01

    Comparable entities → DataTable

    Parallel attributes in columns, tabular figures, sticky header

  2. 02

    Sequence or process → Rail

    The order is the information, and a grid of peers destroys it

  3. 03

    One important object → Plate

    A card says "one of several"; a plate says "here is the thing"

  4. 04

    Attributes of one thing → Ledger

    This is what was being boxed most often

  5. 05

    Relationships → Diagram

    Real SVG with orthogonal routing and edges naming their protocol

  6. 06

    Reference material → Measure

    62–72ch