All work
Custom SoftwareVolunteer medical transport

Chesed Tosh Dispatch

One dispatcher console over a single Postgres domain model, with every driver interaction on plain SMS — a ride goes out to the whole eligible roster at once, the first YES wins it, and the reminders, escalations, and confirmations run themselves.

Product engineer — design & build

chesed tosh — dispatch console
live
Chesed Tosh
Home
Operations
All calls
Messages1
Tasks31
Records
Patients
Visitors
Members
Groups
Hospitals
Contacts
Insight
Reports
Admin
Dispatcher consoleChesed Tosh operations
Call #1057 is approaching its trip time with…+25+ New ▾IF

Command center

Good afternoon, Issac

Wednesday, Aug 12

Last updated 5:29 PM⟳ Refresh
6Open calls
2Uncovered
3Awaiting confirm
4Upcoming today
67%Covered todayof today's resolved calls
Today's callsAll calls →
#1052Mrs. Katzby S. Perlman4:45 PMCovered
#1054Miriam Adlerby Y. Tauber6:00 PMCovered
#1055Chava Lieberby A. Deutsch6:40 PMCovered
#1057Dovid Berger · visiting Mrs. Katz7:30 PMOpen
#1058Rivka Neuman9:00 PMOpen
Needs you now26 items
Approaching uncoveredCall #1057 is approaching its trip time with no driver assigned.Open
Approaching uncoveredCall #1058 is approaching its trip time with no driver assigned.Open

24 more in Tasks →

Recent activity(20)
Call #1052 covered by S. Perlman5:54 PMReminder 1 of 3 sent for #1057 — 25 members7:05 PMRivka Neuman confirmed pickup for #10546:12 PMCall #1051 auto-completed at trip time3:40 PM
01The problem

Where it started.

Dispatching was a phone tree. A coordinator worked down the volunteer list one driver at a time — call, no answer, next — until somebody could take a patient to their appointment. Every minute of that was a minute the ride wasn't placed, and the coordinator was the only place the state of it existed.

Afterwards it got worse, not better. Did anyone actually take the ride? Was the patient told who was coming? Did the driver ever confirm they'd finished? Each of those was a memory exercise, and the patient, driver, hospital, and trip details behind them lived scattered across text threads and informal notes. There was no reliable way to answer how many trips ran or how many kilometres a volunteer had driven — which is exactly what you need for reporting and for recognising the people doing the driving.

The hard constraint was the volunteers themselves. They're unpaid, they're not going to install an app or keep a login, and any system that asked them to would simply not get used. Whatever replaced the phone tree had to meet them where they already were: a text message.

02The approach

How I thought about it.

I built one dispatcher web console over a single Postgres domain model, and put every driver interaction on plain SMS. All the business logic sits in a transport-agnostic services layer that the web UI, the inbound SMS webhooks, and the background jobs all call into — so a ride being covered means the same thing whether a dispatcher clicked it or a driver texted YES from a flip phone.

Making SMS behave transactionally on serverless was the real problem. Every outbound message is written to an outbox inside the database transaction and relayed later by a single background task — never sent in-request, because a serverless function can die after commit — with a uniqueness constraint on an idempotency key that makes duplicate sends impossible and inbound webhooks deduping on the provider's message id. On top of that sits a deliberate revalidate-only scheduling rule: nothing is ever cancelled or rescheduled, so every delayed job re-reads live state when it fires and quietly no-ops if it's stale. A reminder for a ride that was already covered, cancelled, or moved simply does nothing, which removes an entire category of distributed-state bugs. I also built a dev-only virtual phone that speaks the same webhook contract as the real SMS provider, so the whole conversation loop is testable locally without sending a message.

03What I built

The thing itself.

chesed tosh — dispatch console
live
Chesed Tosh
Home
Operations
All calls
Messages1
Tasks31
Records
Patients
Visitors
Members
Groups
Hospitals
Contacts
Insight
Reports
Admin
Dispatcher consoleChesed Tosh operations
Call #1057 is approaching its trip time with…+25+ New ▾IF

Command center

Good afternoon, Issac

Wednesday, Aug 12

Last updated 5:29 PM⟳ Refresh
6Open calls
2Uncovered
3Awaiting confirm
4Upcoming today
67%Covered todayof today's resolved calls
Today's callsAll calls →
#1052Mrs. Katzby S. Perlman4:45 PMCovered
#1054Miriam Adlerby Y. Tauber6:00 PMCovered
#1055Chava Lieberby A. Deutsch6:40 PMCovered
#1057Dovid Berger · visiting Mrs. Katz7:30 PMOpen
#1058Rivka Neuman9:00 PMOpen
Needs you now26 items
Approaching uncoveredCall #1057 is approaching its trip time with no driver assigned.Open
Approaching uncoveredCall #1058 is approaching its trip time with no driver assigned.Open

24 more in Tasks →

Recent activity(20)
Call #1052 covered by S. Perlman5:54 PMReminder 1 of 3 sent for #1057 — 25 members7:05 PMRivka Neuman confirmed pickup for #10546:12 PMCall #1051 auto-completed at trip time3:40 PM
  • Race-safe SMS fan-outA ride is broadcast to the selected volunteer groups at once; the first driver to text YES wins it via a conditional UPDATE, and everyone else is automatically sent a “covered” notice.
  • Driver self-service over SMSOPEN CALLS, REPORT, NAME, DROP, STANDBY, mute-with-duration, and silent hours — a deterministic grammar parses all of it out of whatever a volunteer actually types, and anything it can't read becomes a dispatcher task instead of a dropped message.
  • Escalation & coverage safety netA configurable reminder ladder, per-area pre-trip reminders, auto-flip to uncovered at trip time, auto-complete, and a dispatcher task queue for everything a human still has to chase.
  • Traveller confirmationsThe person actually being picked up gets a confirmation text with a required acknowledgment — and if it never arrives, a “phone them now” task lands in the dispatcher's queue.
  • Direction-aware combine & mergeDetects two rides one car could serve — same patient or hospital, never opposite directions, inside a configurable window — and merges them into a single trip with per-traveller pickups and confirmations.
  • Reports & exportsCalls, drivers, response times, and SMS tabs with KPI deltas and charts, CSV and XLSX export, plus a monthly text to each driver summarising their own trips and kilometres.
  • Admin & templatesCapability-based access control across roles and grants, an audit log, spreadsheet import/export for five entity types, encrypted per-deployment integration credentials, and a Liquid SMS-template editor.
04The result

What changed.

One broadcast reaches every eligible driver at once instead of a coordinator working down a list, and the first YES wins the ride — decided by the database, so two drivers replying at the same moment can't both be assigned.

A volunteer runs their whole side of the system from their texts: take a ride, ask what's open, report kilometres, drop out, go quiet for the night. That was the constraint everything else had to clear — these are unpaid volunteers, and a system that asked them to learn an app is a system that doesn't get used.

25 background jobs handle what a person used to have to remember: reminder ladders, the flip to uncovered at trip time, auto-complete, chasing unconfirmed patients, standing schedules, and monthly driver summaries.

Patients, visitors, members, hospitals, contacts, and groups are structured records instead of scattered notes — and each ride snapshots its own addresses, so editing a record never rewrites the history of a trip that already ran.

Trip and kilometre totals are queryable and exportable rather than reconstructed by hand — so the organisation can report on its year, and see which volunteers to thank.

It ships with a 32-page in-app manual written for the dispatcher rather than the developer, and 411 test files behind it — including a virtual phone that exercises the whole SMS conversation without sending a message.

Outcomes are qualitative — no client metrics shown.

05The stack

Under the hood.

Nuxt 4TypeScripttRPCDrizzle + NeonTrigger.devTwilio SMSBetter AuthVercel
Your project, next

Got a process that
should run itself?

Tell me where the work piles up. I'll show you what a calmer, quieter version of it looks like — built around how your team already works.