Skip to content

Repository files navigation

Digital PEWS - NPEWS Chart UI

Plain HTML/CSS/JS implementation of the NHS National Paediatric Early Warning System (NPEWS) observation chart. No framework, no build step, no dependencies.

This repository provides a bounded scoring and charting component for integration into a wider clinical system. It is not an EPR workflow or a complete SPOT/NPEWS solution and does not independently claim National PEWS compliance. See the product and compliance boundary.

Clinical safety status, known hazards, transferred controls, and release limitations are documented in SAFETY.md. No clinically approved release has been designated.

Prerequisites

  • Docker and Docker Compose (for running services)

Quick start

Using Docker Compose (recommended)

# Start the demo app (http://localhost:8000)
s/up

# Equivalent - start only the demo app
s/up demo

# Start the SMART-on-FHIR sandbox (NPEWS app + local HAPI R4 FHIR server
# seeded with demo patient data + SMART launcher, patient browser,
# FHIR viewer, control panel). Opens the launcher with the NPEWS
# app prefilled - one click lands you on the chart.
# See smart/README.md for what SMART-on-FHIR is and how to use it.
s/up smart

Press Ctrl+C to stop the services. Docker Compose will automatically clean up containers. s/down smart tears down the FHIR sandbox stack; s/down (no arg) tears down everything.

Online demo

A live demo is deployed to GitHub Pages from main:

https://rcpch.github.io/digital-pews/

This is the full demo harness with the scenario sidebar. It updates automatically on every push to main.

Demo app

How the chart works

The chart is a props-driven visualisation component: given a patient and a list of observations it renders into a fixed set of DOM hooks. Data is kept separate from presentation - the chart never carries a specific patient in its markup, and it computes all PEWS scores itself (see below).

The chart/ component is loaded as ES modules (no build step):

  • chart-shell.js - the shared chart DOM scaffold (mountChartShell(host)), used by both the standalone page and the demo harness so they can't drift.
  • chart.js - the rendering engine. Import render and call render({ patient, observations }). It imports its own dependencies:
    • npews-scoring-config.js - age bands, scoring thresholds and age-band bounds.
    • npews-scorer.js - computes the PEWS score, escalation level and applicable age band for every observation from the patient's date of birth. Scores are always computed, never hand-typed - any score in the input data is ignored.
    • age-band.js - pure date maths for resolving the age band(s) an admission spans (supports seamless charting across a birthday boundary).
  • styles.css - all styling (colours, layout).

Two entry points render the chart (both in demo/):

  • demo/index.html - a single standalone chart. Loads demo-data.js (which publishes window.PATIENT / window.OBSERVATIONS), mounts the shell, then calls render.
  • demo/demo.html - the demonstration harness. A left sidebar lists example patients from scenarios.js; selecting one mounts a fresh shell and passes the scenario to render({ patient, observations }). This replaced Storybook.

Use as a Web Component

The chart is also packaged as a framework-neutral <npews-chart> custom element so it drops into any host - a plain page, React/Angular/Vue, or a SMART-on-FHIR app - with no framework dependency. The element self-provisions its stylesheet and fonts, so a consumer only loads one module and feeds it a JSON object:

<script type="module" src="npews-chart.js"></script>

<npews-chart id="chart"></npews-chart>

<script type="module">
  document.getElementById('chart').data = {
    patient: {
      name: 'Alex Thompson',
      dob: '2017-03-14',
      // ...nhsNumber, ward, bed, consultant
    },
    observations: [
      // raw vitals only - no scores; the engine computes them
      { timestamp: '2025-01-10T08:00:00Z', respiratoryRate: 20, spo2: 99, /* ... */ },
      // ...
    ],
  };
</script>
  • Data is passed as a JS property (.data), not an attribute, because it is a rich object. Convenience setters .patient and .observations are also available.
  • Presentation stays separate from clinical data. Set .options = { showDemographics: false } when the embedding host already provides patient identification; the standalone default is true.
  • Scores are always computed from the patient's date of birth and the raw observations - any score in the input is ignored (single source of truth).
  • See chart/example.html for a minimal, fully self-contained drop-in (no demo dependencies, inline JSON data) and demo/embed-example.html for a version that imports from the demo scenario catalogue.

ES modules require an HTTP server. Opening these files directly with file:// will fail with a CORS error. Run s/up (or s/up demo) and visit http://localhost:8000/chart/example.html or http://localhost:8000/embed-example.html. Or use any web server you like (e.g. npx live-server --port=8000 or python3 -m http.server 8000).

Phase 1 limitation: the engine uses fixed DOM ids, so one chart per document is supported today; embed additional charts in separate iframes. Shadow-DOM isolation, multiple instances per page, and an NPM/UMD + Subresource-Integrity CDN bundle with TypeScript prop types are Phase 2 (see spec/roadmap.md).

Layout modes

Three modes are supported, selectable via the toolbar toggle in the UI:

Mode Trigger Chart height
Landscape >1200px or manual 140px
Portrait 768-1199px or manual 90px
Mobile <768px or manual 70px

Auto-detection runs on load. The toolbar lets you override manually. To lock a layout in code, set data-lock-layout="landscape" (or portrait/mobile) on the <body> tag.

Age bands

Four age bands are defined, each with different y-axis ranges, scoring thresholds, and header colours:

Band Label Header colour
0-11m 0 to 11 months Pink
1-4y 1-4 Years Orange
5-12y 5-12 Years Yellow
13+y 13+ Years Grey

All four age bands have demonstration scenarios in demo/scenarios.js (shown in the demo.html sidebar), including a birthday-crossing scenario where a child turns 5 mid-admission and the chart seamlessly joins the 1-4y and 5-12y bands. demo-data.js holds the two full-day datasets reused by those scenarios.

Visual reference

The primary reference image is reference-sources/images/chart-5-12-years-1.png. Use test-output/VISUAL_COMPARISON.md to track which visual elements have been matched against the NHS paper chart.

When working on visual fidelity, keep the reference image and the running chart open side by side.

Fonts

Lato (from Google Fonts) is the default fallback. If you have a Frutiger licence, override the CSS variable in your local stylesheet:

:root {
  --font: 'Frutiger', 'Frutiger LT Std', Lato, sans-serif;
}

Canvas text rendering uses the chartFont(size, weight) helper in chart.js, which reads --font at call time so the override takes effect automatically.

Adding a demo scenario

Demonstration scenarios (the example patients in the demo.html sidebar) live in demo/scenarios.js. Add a plain object to the SCENARIOS array:

{
  id: 'my-scenario',            // unique, used in the URL hash (#my-scenario)
  title: 'Patient Name',        // sidebar label
  ageBand: '5-12y',             // shown as a chip
  description: 'One line describing the clinical picture.',
  patient: { name: 'Patient Name', dob: '2018-05-01', /* ... */ },
  observations: [ /* raw vitals only - NO pewsTotal / escalationLevel */ ],
}

Observations carry raw vital signs only; the chart computes the PEWS score, escalation level and applicable age band from the patient's date of birth. The sidebar hot-reloads on save (live-server).

Specs and reference materials

Start at spec/README.md — the spec index and landing page.

  • spec/spot-npews-ui-spec.md / spec/spot-npews-spec.md - NHS SPOT/NPEWS specification (transcribed from the reference .xlsx)
  • spec/npews-scoring-spec.json - canonical scoring spec (source of truth); spec/npews-scoring-tables.generated.md - generated reference table; spec/npews-scoring.md - clinical narrative
  • spec/data-model.md - the Patient + Observation input shapes and data-entry codes
  • spec/escalation.md - escalation levels, triggers, sepsis and ISBAR
  • spec/fhir.md - FHIR adapter + conformance testing
  • spec/decisions.md - durable decision log; spec/implementation-notes.md - implementation notes + QA checklist; spec/roadmap.md - roadmap
  • reference-sources/images/ - PNG exports of the NHS NPEWS paper charts for each age band
  • reference-sources/*.pdf - source PDFs and specifications

Licence

Source code is licensed under LGPL-3.0-or-later. Documentation and clinical content are licensed under CC-BY-SA-4.0. The NHS SPOT/NPEWS specification and reference chart images remain the property of NHS England.

About

Digital Paediatric Early Warning Score (NPEWS) from the RCPCH

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages