Booking systems
PatientFlow
No more chasing patients for a yes or a no.
- Client
- Independent healthcare practice
- Role
- Product design, build and deployment
- Timeline
- PLACEHOLDER — e.g. 6 weeks end to end
- Year
- 2025
- Status
- Live
- To book someone in and send the confirmation
- Under a minuteTo book someone in and send the confirmation
- Patients just tap a link — no app, no password
- Nothing to installPatients just tap a link — no app, no password
- Today, what's unpaid, and what's still owed
- One screenToday, what's unpaid, and what's still owed
- Confirmations and reschedules come in on their own
- No chasingConfirmations and reschedules come in on their own
Overview
PatientFlow is the booking and patient system for a single-practitioner practice. It replaces a notebook-and-WhatsApp routine with one small web app that holds the patient list, books appointments, sends the confirmation, tracks who still owes money, and opens on a dashboard that answers the only question that matters at 8am: what does today look like?
The practice runs it from a phone. The patients never install anything — they get a link.
Before — manual
- Bookings written into a paper diary
- Confirmation chased over WhatsApp by hand
- No-shows discovered on the day
- Payments remembered, not recorded
- Month-end figures reconstructed from memory
After — automated
- Every booking stored against a patient record
- Confirmation generated and sent in one tap
- Status visible before the patient arrives
- Outstanding balances tracked per appointment
- Revenue and workload on a live dashboard
What it looked like before
The practice never had a lack of effort — it had a problem of everything living in one person's head. A patient would message, a time would be agreed, and the only record was a line in a diary. Confirmation depended on the practitioner remembering to send a message. Whether a patient had paid depended on memory.
What I built
1. Capture the patient once
Patients are stored once — name and phone number — and every appointment hangs off that record. Editing or removing a patient keeps their history attached to the right person instead of a diary entry.
2. Book in under a minute
The whole booking flow is one floating action button: pick the patient, pick a date, pick a time. PatientFlow then does the part that used to be manual — it composes the confirmation message itself, with the appointment details and a personal confirmation link already inside.
3. Let the patient confirm
The patient taps the link and sees a plain page. No login, no app, no account. Two buttons: Confirm appointment or Request a different time.
That single change removed the chasing step entirely. A confirmation turns the appointment green in the schedule; a reschedule request keeps it pending, so the practitioner knows exactly who to call.
4. Close the loop on money
Every new appointment starts as outstanding. When money arrives, one tap marks it paid, and the dashboard's revenue figures move with it. Money became a property of an appointment rather than something someone has to remember.
5. Start the day on one screen
The dashboard is a morning briefing, not a report:
- Today — appointments booked for the day
- Pending — still waiting on a patient confirmation
- Outstanding — appointments with unpaid balances
- Patients — total records
- Total revenue — money actually received
- Outstanding revenue — money still owed to the practice
Below that: upcoming appointments with their status and payment state. The practice opens one page and knows where to spend the next hour.
How it is put together
A deliberately boring stack, because the client needed something maintainable rather than fashionable.
| Layer | Choice | Why | | --- | --- | --- | | Runtime | Node.js + Express | Small surface area, fast to ship, easy hosting | | Data | Turso (hosted libSQL) | SQLite ergonomics with a managed, always-on endpoint | | Views | Server-rendered EJS + Bootstrap 5 | Instant load on a phone, no client framework to maintain | | Auth | Session cookies + bcrypt hashes | One practitioner, one account, no public sign-up | | Messaging | WhatsApp deep links | Zero API cost, zero deliverability risk, works today | | Documents | pdf-lib | Invoices generated on demand from live data |
Server rendering matters more than it sounds: on a mid-range Android phone over patchy mobile data, a page that arrives already assembled beats a page that assembles itself.
What is different now
The manual steps that disappeared: writing the booking down, composing the confirmation, remembering to send it, chasing the reply, and reconciling payments at month end.
The practice now works from status rather than memory. Pending is a colour, not a question. Outstanding revenue is a number, not an afternoon of reconstruction.
Decisions worth explaining
- Server-rendered over SPA — the operator is on a phone; instant paint wins.
- Deep links over the WhatsApp Business API — no approval cycle, no per-message cost, and an identical result for a single-practitioner practice.
- One patient-side page — the only thing the patient ever needs to see.
- Status as the core primitive — pending, confirmed and cancelled drive the colour, the dashboard and the follow-up list.
What I would build next
Engineering honesty, kept visible. This is what I would build next, in priority order.
- Automated reminders for appointments that stay pending past a threshold.
- Recurring appointments for patients who book the same slot weekly.
- Offline tolerance so a booking survives a dropped connection in a consulting room.
- Practice-level reporting across months, not just the current day.
That produced three predictable costs:
- Unconfirmed time. Slots were held open for patients who never replied, because chasing them took longer than the appointment itself.
- Leaked revenue. There was no single place to see which appointments were still unpaid.
- No morning picture. Starting the day meant reading back through messages.
The brief was narrow on purpose: do not build a hospital system, build the smallest thing that removes the chasing.
PLACEHOLDER QUOTE — replace with a sentence from the practice owner about not chasing confirmations any more.
How it's built— for the curious, and for your IT team
- Node.js
- Express
- Turso (libSQL)
- EJS
- WhatsApp deep links
- Session auth
