Case Studies

Hearts in Scrubs: Deep Dive

Hearts in Scrubs is a full clinical practice management system built for a South African wound care specialist. It runs an entire single-practitioner practice from one place: patient records, wound assessments captured at the bedside, an AI clinical scribe, a WhatsApp patient bot, invoicing, and medical aid claims.

This case study explores the technical architecture that lets one developer build and maintain a complete clinical system — and ship changes the same week a nurse asks for them — using LEGO Builder principles.

The Challenge

A wound care practice has a very specific shape, and most off-the-shelf practice-management software fights against it:

Technical Architecture

Data Model

At the centre is the wound assessment — a structured, photo-backed snapshot of a wound at a moment in time, always tied to a patient and a visit:

// models/wound-assessment.js — one block, one responsibility
export const WoundAssessmentModel = {
    tableName: 'wound_assessments',
    fields: {
        id: 'uuid',
        patientId: 'uuid',
        visitId: 'uuid',
        site: 'string',          // anatomical location of the wound
        lengthMm: 'integer',
        widthMm: 'integer',
        depthMm: 'integer',
        tissueType: 'enum',      // granulating, sloughy, necrotic, epithelialising
        exudate: 'enum',         // none, low, moderate, high
        photos: 'jsonb',         // references to encrypted photo storage
        notes: 'text',
        assessedAt: 'timestamp'
    }
};

Bedside Capture, Instant Sync

The nurse captures an assessment on her phone; it is validated and persisted as a single composed block, so the full wound history is available on any device seconds later:

// controllers/assessment-controller.js — orchestration only
export async function recordWoundAssessment(input) {
    ensureClinician(input.actor);                          // guards/
    const assessment = buildWoundAssessment(input);        // builders/
    const photos = await storeEncryptedPhotos(input.photos); // bridges/

    const saved = await saveAssessment({ ...assessment, photos });
    await refreshWoundTimeline(saved.patientId, saved.site); // processors/

    return saved;
}

WhatsApp Patient Bot

Appointment reminders and check-ins go out over Meta's WhatsApp Cloud API directly — no third-party gateway, no per-message markup:

// bridges/whatsapp-bridge.js — the only place that talks to Meta
export async function sendAppointmentReminder(patient, appointment) {
    return whatsappCloudApi.send({
        to: patient.whatsappNumber,
        template: 'appointment_reminder',
        variables: {
            name: patient.firstName,
            date: formatDate(appointment.startsAt),   // utilities/
            time: formatTime(appointment.startsAt)
        }
    });
}

AI Clinical Scribe

The nurse dictates; a processor turns free speech into a structured clinical note she reviews and signs off — she never has to type at a desk after hours:

// processors/clinical-scribe.js — turns dictation into a draft note
export async function draftClinicalNote(audio, context) {
    const transcript = await transcribe(audio);            // bridges/
    const structured = extractClinicalFields(transcript);  // utilities/

    return buildNote({
        patientId: context.patientId,
        visitId: context.visitId,
        subjective: structured.subjective,
        objective: structured.objective,
        plan: structured.plan,
        status: 'draft'      // always clinician-reviewed before it is final
    });
}

LEGO Builder Implementation

Block Organisation

The whole codebase is organised into the same small, predictable categories, so any feature is assembled from blocks that already exist:

src/
├── utilities/    // Pure functions (date/measurement formatting, ICD-10 lookups)
├── builders/     // Object constructors (assessment, note, claim builders)
├── guards/       // Auth, role, and POPIA-consent checks
├── processors/   // Clinical logic (wound timeline, scribe, claim assembly)
├── bridges/      // External integrations (WhatsApp Cloud API, transcription, medical-aid switch)
└── controllers/  // Request handlers and orchestration

Example: Building a Medical Aid Claim

A claim is assembled from blocks — diagnosis codes, procedure codes, and the consultation — then checked by a guard before it is ever sent to the scheme:

// controllers/claim-controller.js
export async function submitMedicalAidClaim(visitId) {
    const visit = await getVisit(visitId);

    const claim = buildClaim({                 // builders/
        member: visit.patient.medicalAid,
        diagnoses: visit.icd10Codes,
        procedures: visit.tariffCodes,
        consultation: visit.consultation
    });

    ensureClaimIsComplete(claim);              // guards/ — throws on missing codes
    return await submitToScheme(claim);        // bridges/
}

Why It Holds Together

Because every block does one thing, the parts that touch patient data stay small and easy to reason about:

Results and Impact

The architecture exists to serve one outcome — the practitioner's day:

Lessons Learned

1. Build for where the work actually happens

The single biggest design decision was mobile-first bedside capture. Everything else — sync, timeline, photos — follows from the fact that a wound care nurse works on her feet, not at a desk.

2. Controllers should orchestrate, not implement

Controllers that just compose guards, builders, processors, and bridges read like a recipe. The clinical logic lives in small processors that are easy to test in isolation.

3. Put every integration behind one bridge

WhatsApp, transcription, and medical-aid submission each have a single integration point. When an API changes, exactly one block changes with it.

4. Keep sensitive logic small

POPIA consent, access control, and photo encryption are concentrated in guards and bridges — small, auditable blocks rather than rules sprinkled across the codebase.

Conclusion

Hearts in Scrubs shows that LEGO Builder architecture scales from a single utility function to a complete clinical practice management system — patient records, wound assessments, an AI scribe, a WhatsApp bot, billing, and medical aid claims — built and maintained by one developer.

By treating every piece of code as a reusable block with a single responsibility, the system stays fast to change and easy to maintain: exactly what a busy wound care practice needs.

← Back to Blog