Demo — not a medical device — synthetic data only

Central monitoring station · Portfolio project

Twelve beds on one screen, and the alarm that matters stands out.

An ICU central station for a 12-bed unit: live ECG and pleth sweeps, vital signs, NEWS2 and qSOFA, and an alarm system inspired by IEC 60601-1-8 — priorities, acknowledgement, a 120 s audio pause that re-arms, escalation. Open with no sign-in: the physiology is shared, your actions stay yours.

Demo — not a medical device — synthetic data only. Work in progress.

The Excubia central station: twelve bed tiles with ECG II and pleth sweeps, heart rate, SpO₂, blood pressure, respiration and temperature, NEWS2 and qSOFA; a high alarm on bed 07 escalated to the charge nurse, the active alarms listed by priority on the right
01 · The need

A long shift, many beds, little room for error.

An ICU nurse watches several beds through a 12-hour shift; an intensivist decides from trends, scores and alarm history. Three things decide whether the right patient gets attention in time.

01

Every bed at a glance

Twelve beds on one screen: ECG II and pleth sweeping live, heart rate, SpO₂, blood pressure, respiration and temperature, with NEWS2 and qSOFA beside them.

02

Alarms that earn attention

Too many alarms and the one that matters gets missed. Priorities read by marker, flash and sound; a condition must hold before it sounds, and a repeat arrives as one alarm with a counter.

03

Every action on record

Who acknowledged, who paused, who changed a limit, and on which patient: each action names the bed, the patient and the identifier, and lands in an audit trail nobody can rewrite.

02 · The rules

What the station holds to.

A few rules every screen keeps, because a monitor that is wrong quietly is worse than one that says it does not know.

01

Never a stale value as current

A signal with no fresh sample turns into grey hatched NO DATA with its age. Gaps are drawn as gaps; nothing is interpolated as if it had been measured.

02

Never colour alone

High, medium, low and technical alarms each carry a marker (!!!, !!, !, TECH), a flash rate and an audio pattern, after the conventions of IEC 60601-1-8.

03

Scores only on fresh inputs

NEWS2 and qSOFA are computed from current values only. A score with a stale or missing input says so — NEWS2 — SpO₂ n/a — rather than pretending.

04

A demo, and it says so

Not a medical device, no compliance claimed, synthetic data only: fictitious names, SIM- record numbers, and a banner on every screen.

03 · The station

Built and running.

Stills of the live station and of its design-system page: twelve synthetic patients, sweeping in real time.

Bed 07 in high alarm: the red band reads ART MAP LOW 55 < 65, escalated, the arterial pressure highlighted, ECG II and pleth sweeping above the numerics
A high alarm on bed 07, escalated to the charge nurse
The active alarms list, sorted by priority then onset: a high alarm escalated to the charge nurse, a medium one unacknowledged, each with Pause 2:00 and Acknowledge
Active alarms, by priority then onset
The design-system page's alarm priorities: high flashes at 2.0 Hz with ten pulses at 880 Hz, medium at 0.7 Hz with three, low steady with one, technical with a dashed outline; below, bed tiles in normal, pending and high states
Alarm priorities: marker, flash rate and sound
Every state of the alarm band: none, pending under a validation delay, high active, escalated, acknowledged and latched, medium active, audio paused and de-duplicated, low, and technical
The alarm band in every state of its machine
Bed tiles with leads off, a sensor off, a stale signal and the stream lost, each value replaced by NO DATA with its age, the waveform hatched
Leads off, sensor off, stale, stream lost: NO DATA
The whole central station: twelve bed tiles, the unit's alarm counts in the header, the active alarms on the right, the demo banner above
The central station, twelve beds and the alarm list
04 · Choices

Weighed, chosen, and why.

Each key decision, with the alternatives, the choice and its reason. Each one is written down as a decision record in the repository.

  1. 01

    Where the alarms live

    Weighed
    In the browser · on the server, with XState · on the server, hand-written
    Chosen
    On the server: a pure, hand-written state machine, one per bed and condition, stepped on the simulated clock.
    Because
    Every station agrees, alarms keep escalating with no browser open, every step is audited, and the suite can iterate the whole transition table.
  2. 02

    Drawing the waveforms

    Weighed
    WebGL · Canvas 2D on the main thread · Canvas 2D in a worker
    Chosen
    Canvas 2D in one render worker that owns every OffscreenCanvas, sweeping only the new pixels.
    Because
    A sweep touches a few pixels per trace per frame, so WebGL buys nothing; off the main thread, React never competes with the traces.
  3. 03

    Getting samples to the screen

    Weighed
    JSON · Server-Sent Events · binary WebSocket frames
    Chosen
    Binary WebSocket frames for the waveforms, batched every 80 ms with a sequence number; state as compact JSON at up to 4 Hz.
    Because
    The bulk stays small and fast to decode, a gap is told from a late chunk, and the state schema stays readable.
  4. 04

    Standing in for the bedside monitors

    Weighed
    A module inside the API · a service of its own
    Chosen
    A deterministic physiological simulator as its own service, reached through the port a real monitor gateway would implement.
    Because
    A real process boundary: stopping the simulator shows a lost feed end to end, and the same seed always gives the same bytes.
  5. 05

    Who acts on the unit

    Weighed
    A real sign-in · one shared unit · a private sandbox per visitor
    Chosen
    No sign-in: everyone sees the same physiology, and each visitor's acknowledgements, pauses and limits stay in a private sandbox.
    Because
    Zero friction for a reviewer, no personal data, and no visitor can silence another's alarms.
  6. 06

    Storing the record

    Weighed
    MySQL with Prisma · PostgreSQL with pg and plain SQL
    Chosen
    PostgreSQL through pg and numbered SQL migrations.
    Because
    The audit trail is append-only in the database itself — a trigger refuses any update, and any delete outside the sandbox purge — and empty minutes in trends stay explicit.
05 · How it's built

From the simulated bedside to the station.

Three processes on one server, and a shared model between them: the same boundaries a real unit's monitor gateway would draw.

01

Simulator

A Nest service of its own: seeded PRNG, virtual clock, ECG, pleth and respiration, numerics, scripted scenarios. Same seed, same bytes.

02

API

Nest 12 on PostgreSQL: freshness, NEWS2 and qSOFA, alarm conditions once for all, alarm machines per visitor sandbox, the hash-chained audit trail.

03

Station

Next 16 and React 19 on Tailwind v4: a stream worker decodes the binary frames, a render worker sweeps the traces, React gets the state.

04

Shared model

Plain TypeScript used by all three: the wire codec, the PRNG, the scores, the alarm state machine.

06 · Status

What is built, and what is next.

Built ticket by ticket, each decision written down as it is taken.

Built · the station

  • Central stationTwelve bed tiles with ECG II and pleth sweeps, HR, SpO₂, NIBP or ART, RR and temperature, NEWS2 and qSOFA, the unit's alarm counts and the active-alarm list.
  • Stale-data detectionPer signal: leads off, sensor off, stale and stream lost each read NO DATA with their age, never the last value.
  • Design systemThe PFA design system in its dark palette with Excubia's clinical tokens, every tile and band state shown live at /design-system.

Built · the alarms

  • Priorities and annunciationHigh, medium, low and technical, each with its marker, flash rate and audio pattern.
  • The machineValidation delays, de-duplication, acknowledgement, the 120 s audio pause with re-arm, escalation to the charge nurse, latching.
  • Visitor sandbox and auditPrivate actions over shared physiology, each one written to an append-only, hash-chained audit trail.

Next

  • Patient detailLarger traces, trends over 1, 8 and 24 hours, the NEWS2 breakdown, the events timeline, alarm limits.
  • Patient flowAdmit, transfer with two identifiers checked against the wristband, discharge, SBAR handover.
  • Case studyThe problem, the constraints, each trade-off, with figures from a measured run.

See it run,
on twelve synthetic patients.

Acknowledge an alarm, pause its sound for 120 s, watch it re-arm. Your actions stay in your own sandbox; nobody else's station changes.