A fully self-contained, offline-capable, single-file web application for generating and managing EWTD-compliant medical staff rosters. No server, no build pipeline, no internet connection required — just open src/index.html in a modern browser.
- What the Application Does
- Prerequisites
- Installation
- Running the Application
- Running the Tests
- Configuration Options
- Shift Types
- EWTD Compliance Rules
- Supported Regions & Public Holidays
- Exporting Rosters
- Data Storage & Privacy
Medical Roster is an EWTD-compliant staff rostering tool designed for healthcare administrators. It provides:
- Automated roster generation — a greedy, constraint-respecting algorithm assigns shifts to staff members across a configurable reference period (up to 17 weeks, up to 50 staff) in under 5 seconds.
- EWTD compliance enforcement — all four Working Time Directive rules are checked automatically. Any violation is surfaced with a precise, human-readable message (e.g. "Minimum 11-hour rest not met between shift A and shift B").
- Monthly calendar view — fully navigable month-by-month calendar with weekends and public holidays clearly distinguished. Roster entries are colour-coded by shift type.
- Staff management — add, edit, and remove staff members with per-member constraints including absence dates, approved leave periods, shift-type restrictions, and contracted hours — all without page reload.
- Rest-day logic — optional automatic insertion of mandatory rest days based on configurable criteria (e.g. post-night-shift recovery, maximum consecutive shifts).
- Three shift configurations — 24-hour rolling, 12-hour day/night split, and sub-divided day portions (AM/PM/evening).
- Export — download the completed roster as CSV or HTML, or print to PDF via the browser print dialog.
- Offline, zero-dependency — all logic, styles, and bundled public holiday data are inlined in a single HTML file. No CDN, no backend, no analytics.
- A modern browser: Google Chrome (current stable), Mozilla Firefox (current stable), or Microsoft Edge (current stable).
- No internet connection, server, or build tools required.
- Node.js v16 or later (the tests use only Node.js built-ins; no
npm installstep is needed).
No installation is needed to run the application itself.
git clone <repo-url>
# or simply download the repository as a ZIP and extract it
The application works correctly when served from any path, e.g. /tools/roster.html. No root-relative paths are used.
# Example: Python simple server (optional, for hosted deployment)
python3 -m http.server 8080
# Then open http://localhost:8080/src/index.html- Navigate to the
src/directory in your file manager (or via the terminal). - Open
src/index.htmldirectly in Chrome, Firefox, or Edge.
# Linux / macOS
xdg-open src/index.html # Linux
open src/index.html # macOS
# Windows
start src\index.htmlThe application loads immediately. Your staff list and roster configuration are automatically saved to browser localStorage and restored on every subsequent visit — no re-entry required.
An in-page Instructions section (accessible from the top navigation) guides new users through:
- Selecting a region and reference period.
- Adding staff members and their constraints.
- Choosing a shift type.
- Generating a compliant roster.
- Reviewing and resolving any EWTD violations.
- Exporting the finished roster.
All tests are plain Node.js scripts — no test runner or npm install is required.
npm testThis runs the persistence, EWTD compliance engine, and rest-day logic test suites in sequence.
# Persistence / localStorage layer
npm run test:persistence
# EWTD compliance engine (all four rules)
npm run test:ewtd
# Rest-day rostering logic
npm run test:rest-day
# Full roster generation algorithm
npm run test:roster
# Comprehensive EWTD suite
node tests/ewtd_comprehensive_suite.test.js
# localStorage persistence validation
node tests/localstorage_persistence_validation.test.js
# Performance benchmark (50 staff × 17 weeks)
node tests/performance_benchmark.jsEach test script prints a summary to stdout. The performance benchmark additionally reports the elapsed time for roster generation. All tests exit with code 0 on success and 1 on failure.
All configuration is performed within the application UI and persisted automatically. The options below correspond to the settings panels in the app.
| Setting | Description | Default |
|---|---|---|
| Region | Public holiday calendar to apply. See Supported Regions. | england-wales |
| Reference Period Start | First date (YYYY-MM-DD) of the EWTD 17-week averaging window. | Current week Monday |
| Reference Period End | Last date of the reference period (auto-calculated from start + weeks). | 17 weeks later |
| Reference Period Weeks | Length of the averaging window (default 17, as per EWTD). | 17 |
| Setting | Description |
|---|---|
| Shift Type | One of 24h (rolling), 12h (day/night split), or subdivided (AM/PM/evening portions). See Shift Types. |
| Handover Minutes | Additional minutes added to each shift's duration to account for clinical handover (counted towards working hours). |
| Rest-Day Logic Enabled | Toggle automatic insertion of mandatory rest days (see Rest-Day Logic). |
Each staff member supports the following fields:
| Field | Description |
|---|---|
| Name | Display name (stored in localStorage only). |
| Contracted Hours / Week | Used for EWTD-001 averaging and shift allocation weighting. |
| Shift Restrictions | Permitted shift codes for this member (e.g. day-only, no nights). |
| Absence Dates | Individual dates the member is unavailable (marked ABSENT). |
| Leave Periods | Date ranges for approved leave (marked LEAVE). |
| 48-hour Opt-Out | Whether this member has individually opted out of the 48-hour weekly maximum (EWTD-001 still logged as informational). |
When Rest-Day Logic is enabled:
| Criterion | Description | Default |
|---|---|---|
| Max Consecutive Shifts | Force a REST day after this many consecutive working days. |
7 |
| Post-Night Rest Days | Number of mandatory rest days to insert after a night-shift block. | 1 |
A single shift covering a full 24-hour period. Configurable start and end times (typically 08:00–08:00 next day).
Two shifts per day:
| Shift | Default hours |
|---|---|
| Day | 09:00 – 21:00 |
| Night | 21:00 – 09:00 (next day) |
Up to three named portions within the day shift, for example:
| Label | Default hours |
|---|---|
| AM | 09:00 – 13:00 |
| PM | 13:00 – 17:00 |
| Evening | 17:00 – 21:00 |
All start and end times for each shift type are configurable in the Shift Settings panel.
The compliance engine (src/ewtd_compliance_engine.js) enforces four rules automatically:
| Rule ID | Rule | Threshold |
|---|---|---|
| EWTD-001 | Maximum average working week | ≤ 48 hours over the reference period |
| EWTD-002 | Minimum rest between consecutive shifts | ≥ 11 hours |
| EWTD-003 | Minimum in-shift break for long shifts | ≥ 20 minutes for any shift > 6 hours |
| EWTD-004 | Minimum rest days | At least one 24-hour rest day per 7-day period |
Every violation is reported with:
- The rule ID and description.
- The affected staff member's name.
- The specific date(s) involved.
- A human-readable message detailing the exact breach (e.g.
"8.5 h rest recorded between Day 2025-06-10 and Night 2025-06-11; minimum is 11 h").
The roster generation algorithm will either produce a zero-violation roster or explicitly flag every violation — it will never silently ignore a breach.
Holiday data is statically bundled inside the HTML file for years 2023–2028. No network request is ever made.
| Region key | Coverage |
|---|---|
england-wales |
England & Wales bank holidays |
scotland |
Scottish bank holidays (including St Andrew's Day) |
northern-ireland |
Northern Ireland bank holidays (including St Patrick's Day, Battle of the Boyne) |
ireland |
Republic of Ireland public holidays |
Public holidays are visually distinguished in the calendar view and are treated as non-working days by default during roster generation.
From the Export panel in the application:
| Format | How |
|---|---|
Use the browser's built-in Print dialog (Ctrl+P / Cmd+P). The page is print-optimised with CSS @media print rules. |
|
| CSV | Download a machine-readable CSV file of all assignments for the selected period. |
| HTML | Download a standalone HTML snapshot of the rendered roster for archiving or sharing. |
All exports include the full roster data without loss of information.
- All data is stored exclusively in your browser's
localStoragefor the domain/path from which the file is opened. - No data is transmitted to any server, third party, analytics service, or telemetry endpoint — ever.
- To clear all stored data, use your browser's developer tools to clear
localStorage, or use the Reset option within the application settings panel. - Staff names and scheduling data never leave the user's own browser.
Built by HermesOrg — an orchestration of distinct AI personas working in concert. Product Manager → Designer → Engineer → QA, each contributing expertise to build something real.