Nursing Kanban Board
Master plan for the ward nursing kanban surface.
Status: Proposal — 2026-05-14 Owner: plan@everapp.io Tagline: Don’t build a new Jira. Mount a Kanban view on top of the systems we already have, and let nurses use the same board for clinical work, sprint review, and feature requests.
1. Thesis
We have ~80% of a Kanban platform spread across 6 systems:
| Jira concept | medOS equivalent (already shipped) |
|---|---|
| Issue / Card | Order + AcknowledgementRequest + FocusList item + medical-worklist row |
| Board | department_queues (per dept, per status column) |
| Column / Status | MASTER_WORKFLOW_NODES (typed state machine) |
| Swim lane | Patient × encounter × nurse × shift |
| Workflow rules | policy_gates (transition gates) + workflow_templates (graph) |
| Notifications / Watchers | AcknowledgementRequest + central notification system |
| Sprint | NurseShift (morning / noon / night / เวร) |
| Retrospective | Care-plan evaluation column (already modeled in interfaceData2.ts) |
| Activity feed | hospital_events + audit logs |
| Board config | worklist-editor + main-flow-editor (visual workflow graph) |
| Recurring reviews | cron_jobs registry |
| Card layout config | Worklist-editor tab/column UI |
| Bulk actions | BulkActionToolbar (nutrition miniapp) — already reusable |
What we’re missing is the visual surface that unifies them and a thin “shift = sprint instance” wrapper. That’s it. No new database, no new realtime layer, no new permissions model.
2. Three boards, three timescales
A ward needs three concurrent boards, all backed by the same cards:
| Board | Cadence | Source | Audience |
|---|---|---|---|
| Shift board (live operations) | 8-hour shift | department_queues + active orders + open FocusList problems + pending acks |
Floor nurses |
| Care-plan board (per-patient) | Per encounter, days→weeks | FocusList items + linked interventions + evaluation status |
Charge nurse, primary nurse |
| Ward improvement board (meta) | Sprints of 1–2 weeks | Feature requests, policy-gate tweaks, equipment issues, training notes | Head nurse, ward manager, super-admin |
All three use the same card schema, the same drag-drop UX, the same filters. Just different default filters and column sets.
3. The card — one schema, five flavors
interface KanbanCard {
id: string; // stable across realtime updates
source: 'order' | 'focus' | 'ack' | 'worklist' | 'improvement';
sourceRef: string; // FK back to the originating entity
title: string; // problem name / order name / ack subject
patientRef?: { _id: string; hn: string; name: string };
encounterRef?: string;
ward: string; // routing
status: string; // MASTER_WORKFLOW_NODES state id
priority: 'routine' | 'urgent' | 'stat';
assignee?: { _id: string; name: string; role: string };
watchers?: string[]; // ack escalation chain
due?: Date; // RRULE-derived for repeating
shiftId?: string; // sprint instance — see §5
labels?: string[]; // free-form chips (NANDA Dx, focus group, etc.)
color?: string; // derived (priority / NEWS2 / overdue)
badges?: { news2?: number; mews?: number; falls?: 'high' | 'med' | 'low' };
links?: { type: 'blocks' | 'blocked-by' | 'relates' | 'evaluates'; cardId: string }[];
createdAt: Date;
updatedAt: Date;
// Optional render-on-card details, lazy-loaded:
detail?: KanbanCardDetail;
}
No new table. KanbanCard is a view-model, projected by a small Supabase view (or edge function) that unions:
department_queuesrows (operational queue)orderswith status (medication, lab, imaging, procedure)acknowledgement_requestswith statusfocus_listitems (care plan)improvement_cards(one new tiny table — the only net-new schema)
Each row tags its source. Frontend can filter / split / merge cards by source without round-tripping.
4. Columns — derive, don’t hardcode
Columns come from the workflow template attached to the ward (workflow_templates).
- Default ward template ships with 6 columns:
To do → Doing → Awaiting result → Awaiting sign-off → Done → Carried over. - Per-ward templates override (ICU has
Pre-procedure → In-procedure → Recovery → Discharge). - Column transitions are gated by
policy_gatesrows (already live). - Drag-drop calls the existing
workflowActionHandler— no new state machine.
This is exactly the main-flow-editor model. The board UI is a horizontal projection of an existing workflow graph.
5. Sprint = Shift instance (the one net-new concept)
Sprints in nursing already exist — they’re called shifts (เวร). One small table:
create table nursing_shifts (
id uuid primary key default gen_random_uuid(),
ward text not null,
shift_type nurse_shift not null, -- existing enum: morning/noon/night
date date not null,
start_at timestamptz not null,
end_at timestamptz not null,
charge_nurse_id text,
staff_ids text[],
handover_from uuid references nursing_shifts(id),
handover_to uuid references nursing_shifts(id),
status text default 'planning', -- planning | active | handover | closed
notes text,
created_at timestamptz default now()
);
create index on nursing_shifts (ward, date, shift_type);
That’s the entire new schema. Everything else hangs off shift_id as a label/filter on existing cards.
Lifecycle:
- Shift planning (15 min before start) — board opens in “planning” mode. Pull carried-over cards from previous shift, accept handover packet, claim assignments.
- Shift active — normal board operations.
- Shift handover (15 min before end) — board switches to “handover” mode. Generate handover packet: completed cards, in-flight cards, escalations, new problems opened. Acknowledgement chain to incoming charge nurse.
- Shift closed — read-only. Retrospective metrics computed by a cron job (median time-to-complete per source, # carried over, # escalated, NEWS2 worsening events).
6. Retrospective / Regression review — ride the evaluation column
The nursing-care-plan format already has evaluation as a first-class field in interfaceData2.ts. The board treats it as a column with two flavors:
- Per-shift retrospective — at shift close, surface cards whose interventions completed and ask the charge nurse to write the evaluation. Hijack
AcknowledgementRequestfor the sign-off. - Per-encounter regression — when an encounter discharges, run a cron-job-scheduled review: every focus opened during the encounter, every linked intervention, every evaluation. Cards that closed without evaluation = QA flag, posted to the ward improvement board.
This is the same evaluation field nurses already fill in. We’re not adding a new ritual — we’re surfacing the existing one as a column.
7. Ward improvement board — the “new features for them” surface
A 6th card source: improvement_cards. One small table:
create table improvement_cards (
id uuid primary key default gen_random_uuid(),
ward text not null,
category text not null, -- 'feature' | 'bug' | 'policy' | 'equipment' | 'training'
title text not null,
description text,
reporter_id text not null,
reporter_role text,
priority text default 'medium',
status text default 'triage', -- triage | accepted | in-progress | done | rejected
assigned_to text, -- admin / dev / vendor
linked_policy_gate_id uuid references policy_gates(id),
votes int default 0,
attachments jsonb,
created_at timestamptz default now(),
updated_at timestamptz default now()
);
This is the channel for nurses to file:
- “The MAR dialog doesn’t auto-focus the dose field” → routes to dev queue
- “We need a column for restraint-check time” → links to a
policy_gateproposal - “The blanket warmer in Room 4 broke again” → routes to facilities
- “I want training on the new IV pump” → routes to in-service ed
Cards triaged by ward manager become input to the actual cron_jobs admin UI, the policy-gates admin UI, or routed to whoever owns the area. Same drag-drop board, different default filter.
8. What to ride / hijack (concrete file paths)
| Existing system | Hijack as | Path |
|---|---|---|
department_queues read model |
Card source for operational queue | infrastructure/medbase/migrations/021_*.sql and successors |
MASTER_WORKFLOW_NODES |
Column definitions | workflowState.ts |
policy_gates |
Column transition rules | policy-gates.md |
workflow_templates |
Per-ward board template | worklist-editor/ |
worklist-editor |
Board settings UI (card layout, columns) | same |
main-flow-editor |
Visual column-graph editor for ward admins | main-flow-editor/ |
workflowActionHandler |
Drag-drop → state transition | workflowActionHandler.ts |
AcknowledgementRequest |
Card sign-off / escalation / reminders | acknowledgement-system.md |
cron_jobs registry |
Scheduled retrospectives + regression review | cron-jobs-registry.md |
manifest-data-layer |
Card data transport with realtime + adapter pattern | manifest-data-layer/ |
useManifestMedicalWorklist hook |
Board data hook | same |
NurseShift enum |
Sprint type | interfaceData2.ts |
FocusList (goal/outcomes/assessment/intervention/evaluation) |
Card structure for care plan | same |
NursingCarePlanTarget (2759 LOC sandbox) |
Card detail dialog | NursingCarePlanTarget.tsx |
BulkActionToolbar (nutrition) |
Multi-select card operations | BulkActionToolbar.tsx |
QueueManagementFloater |
Per-page board FAB | queue-management-floater.md |
hospital_events → orchestrator |
Realtime card updates | encounter-orchestrator-triggers.md |
dynamic-sheet-labour-room-v2 Bento toolbar pattern |
Sub-toolbar for board actions | (just landed in 2d9d4192) |
Order system (medical-kit/src/order/) |
Card source: medication / lab / imaging / procedure orders | many files |
Don’t build: new DB realtime, new notification system, new permissions, new audit log, new schedule engine, new bulk-edit, new bilingual layer, new state machine. All exist.
9. Phased build
Phase 0 — Read-only Kanban view (1 module-loop, ~3 days)
- One sandbox target:
WardKanbanTarget. - Card view-model union over
department_queues+ open orders +focus_list+acknowledgement_requests. - Columns from a hardcoded default workflow template (no policy gates yet).
- No mutations — just render cards in columns with filter by ward / shift / nurse.
- Realtime via existing manifest-data-layer subscriptions.
- Demo: “here are all the work items for Ward 4 right now, grouped by status.”
Phase 1 — Drag-drop + policy-gated transitions (1 loop)
- Wire drag-drop to existing
workflowActionHandler. - Pull column definitions from
workflow_templatesper ward. - Honor
policy_gateson transitions — if denied, snap back + show the gate’sdenial_reason. - Demo: “drag a MAR card from To-do → Doing; cashier hold blocks discharge card; policy rule live-editable.”
Phase 2 — Shift sprint wrapper (1 loop)
nursing_shiftstable + planning/active/handover/closed lifecycle.- Shift filter on board, handover-packet generator (PDF via printing service).
- Acknowledgement chain for handover sign-off.
- Demo: “morning charge nurse hands off to noon shift; carried-over cards auto-attach to new shift.”
Phase 3 — Care-plan board with intervention→evaluation linking (1 loop)
- Repurpose
NursingCarePlanTargetas card detail dialog. - Add
evaluationcolumn to the per-patient board view. - Acknowledgement-system hooks for charge-nurse evaluation sign-off.
- Demo: “open IICP focus card; see linked interventions across 3 shifts; sign off evaluation.”
Phase 4 — Ward improvement board (1 loop)
improvement_cardstable + admin routing.- Free-form card creation from any board (“Report an issue with this column”).
- Triage filter for ward manager.
- Link improvement → policy_gate proposal (deep-link into existing policy-gates admin UI).
- Demo: “nurse files MAR-autofocus feature; ward manager triages; routes to dev queue; one-click create policy-gate.”
Phase 5 — Sprint review + regression review automation (1 loop)
- Cron-job: shift-close retrospective (metrics per source, NEWS2 worsening, carried-over count).
- Cron-job: encounter-discharge care-plan regression (unevaluated focus → QA flag).
- Read-only metrics dashboard per ward.
- Demo: “ward KPI page; click into ‘unevaluated focus’ flag; see exactly which encounter, which nurse.”
Phase 6 — Mount in production routes
/ward/:wardId/board— shift board./encounter/:id/care-plan-board— per-encounter board./ward/:wardId/improvement— ward improvement board./admin/ward-boards— head nurse / super-admin overview.- Register all 4 as
DynamicCoreApp.WARD_KANBAN_*so they can be embedded in patient profile tabs / clinic workspace widgets.
Total: 6 loops, ~3 weeks if focused. Phase 0 is demoable on its own.
10. Risks / tradeoffs
| Risk | Mitigation |
|---|---|
| Card source union becomes a 4-table JOIN nightmare | Use a materialized view refreshed on hospital_events, not live JOIN |
| Drag-drop fights with policy gates | Optimistic UI + snap-back; never let the card commit before backend confirms |
improvement_cards becomes a feature graveyard |
Ward manager must triage within 7 days (cron-job nag); votes from nurses bubble up |
| Per-ward column customization explodes config surface | Ship 3 ward templates (general / ICU / OR-recovery); custom only via head-nurse override |
| Shift handover packet becomes a PDF nobody reads | Make it the board state itself — handover = next shift opens the same board pre-filtered |
| Performance with 200+ cards per ward | Virtualize columns; cards lazy-load detail; pagination at 50 per column |
| i18n burden (TH primary, EN secondary, JA/FIL for market packs) | Card schema is data — labels are template-driven; no new translation keys for the engine |
| “Yet another board” rejection by nurses | Don’t ship as net-new; replace the existing focus-list table view with the board, keep table view as a toggle |
11. The hijack opportunity that ties it all together
The single biggest leverage: the board is just a different rendering of the existing workflow graph. Every clinical workflow already has a workflow_template with MASTER_WORKFLOW_NODES. Today we render those as:
main-flow-editorgraphs (admin)worklist-editortabs + queues (operational)- Patient-journey timelines (per-patient)
Adding Kanban as a 4th rendering is mostly UI work. Same nodes, same edges, same policies. Different camera angle.
If we land Phase 0, we get this for free in 12 other places:
- Doctor consult worklist → Kanban
- Lab specimen tracking → Kanban
- Pharmacy verification queue → Kanban
- OR scheduling → Kanban
- Discharge pipeline → Kanban (the existing IPD discharge cockpit is already 90% this shape)
- Imaging acknowledgement queue → Kanban
- Cashier billing queue → Kanban
So this isn’t a nursing feature — it’s a rendering primitive for the whole workflow layer. Nursing is just the best beachhead because (a) nurses already think in shift cycles, (b) the care-plan format already has assessment → intervention → evaluation columns, and © the NursingCarePlanTarget prototype proves the UX.
12. First concrete step
If approved, the smallest demoable slice:
- Create
web/sandbox/targets/WardKanbanTarget.tsx(~400 LOC). - Use
useManifestMedicalWorklistfor data, group byMASTER_WORKFLOW_NODESstate. - Hardcode 6 columns for “general ward” template.
- Wire 3 card sources: orders, focus list items, pending acknowledgements.
- Filter chips: ward, shift, nurse, priority.
- Drag-drop optimistic only (no policy gates yet).
Demoable in one sitting on http://localhost:5179/?target=WardKanban. Decision point at the demo: do we proceed to Phase 1, or pivot.