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 project is now managed by the Open Health Technology Foundation (OHTF), with development at ohtf/digital-pews, following RCPCH's indefinite pause of its PEWS work. The original RCPCH repository is being archived. This is an independent continuation, not a claim of continuing RCPCH sponsorship or clinical approval; existing attribution and copyright notices are retained.
When major project announcements are warranted, they should also be published on openhealthtechnology.org. Website updates are made through the ohtf/openhealthtechnology.org-website repository, coordinated with the project maintainers.
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://ohtf.github.io/digital-pews/demo.html
This is the full demo harness with the scenario sidebar. It updates automatically on every push to main.
Documentation and guided scenarios: https://ohtf.github.io/digital-pews/. This is now the default landing page. Scenario pages keep the Zensical header and navigation around an isolated interactive demo. Old /docs/ paths on this site redirect; the standalone harness and embedding examples keep their existing paths. The former single-chart root page is available at /single-chart.html on the published site. Redirects on the former RCPCH domain remain under that repository's control.
For local documentation preview, install the documentation-only tools and run s/docs; see s/README.md. The chart itself still has no build step or runtime dependencies.
Demo app¶
- Serves at http://localhost:8000
- Uses live-server for automatic reload
- Volume-mounted from
chart/anddemo/ - Open http://localhost:8000/demo.html for the demonstration harness (left sidebar of example patients); http://localhost:8000/ renders a single chart.
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. Importrenderand callrender({ 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. Loadsdemo-data.js(which publisheswindow.PATIENT/window.OBSERVATIONS), mounts the shell, then callsrender.demo/demo.html- the demonstration harness. A left sidebar lists example patients fromscenarios.js; selecting one mounts a fresh shell and passes the scenario torender({ 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.patientand.observationsare also available. - Presentation stays separate from clinical data. Set
.options = { showDemographics: false }when the embedding host already provides patient identification; the standalone default istrue. - 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.htmlfor a minimal, fully self-contained drop-in (no demo dependencies, inline JSON data) anddemo/embed-example.htmlfor 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. Runs/up(ors/up demo) and visithttp://localhost:8000/chart/example.htmlorhttp://localhost:8000/embed-example.html. Or use any web server you like (e.g.npx live-server --port=8000orpython3 -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:
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¶
Reader-facing documentation starts at docs/index.md. The ED-PEWS development scope tracks the newly collected NHS England ED charts; ED support is not yet implemented. The existing inpatient reference PDFs remain unchanged.
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 narrativespec/data-model.md- the Patient + Observation input shapes and data-entry codesspec/escalation.md- escalation levels, triggers, sepsis and ISBARspec/fhir.md- FHIR adapter + conformance testingspec/decisions.md- durable decision log;spec/implementation-notes.md- implementation notes + QA checklist;spec/roadmap.md- roadmapreference-sources/images/- PNG exports of the NHS NPEWS paper charts for each age bandreference-sources/*.pdf- source PDFs and specifications
Development versions¶
The component is currently 0.1.0, with an experimental API and no clinically approved release. Versions are single-sourced in package.json; release tooling updates its lockfile and browser-visible mirror together. s/version++ patch --dry-run shows a proposed bump; after explicit maintainer approval, s/version++ patch or minor lands the release commit and starts the tested CI tag/prerelease cascade. All 0.x snapshots are development prereleases, not clinical approval. See the changelog.
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.