-
-
MediTriage home. Three intake paths (form, chat, voice) and a one-click Judge Demo that runs the full loop in under three minutes.
-
Staff dashboard. AI-detected red flags, clinical briefing, and an "AI Suggested · Awaiting Clinician Confirmation" tag on every card.
-
Simulated ESP32 beacon firing on a Level 1 alert. Red LED pulse, OLED panel, two short 880 Hz beeps. Ack writes a named audit entry.
-
Structured intake. Chief complaints grouped by clinical category so a non-clinical receptionist still captures the right starting point.
-
Multi-turn chat intake. One question at a time, structured fields extracted live in the sidebar. Thirteen turns to a complete record.
-
20+ MeDo sessions. ~140 prompts. 8 schema iterations. 0 lines of boilerplate copied. Iteration log documents six representative prompts.
Inspiration
We are two electrical engineering students in Nairobi. The clinics we have seen here, the ones serving people who cannot afford private hospitals, run on a model that quietly hurts people. One intake desk. No triage nurse. The queue sorts by who walked in first.
A mother brings in a two-year-old with a fever. Reception writes "fever" on the form and the child gets queued behind seven other patients. Forty-five minutes later when a clinician finally sees them, the child is mottled, breathing fast, and barely responsive. Sepsis. The window for early antibiotics is closing. The child looked fine at the front desk because two-year-olds compensate until they crash, and the person at reception is not a clinician and has no way to know the difference.
This is the single most documented missed-triage failure in primary care. It happens with febrile kids, with stroke patients whose speech is just a bit off, with diabetics in early DKA who walked in saying they felt tired. The technology to catch these patterns at intake exists. It just has not been packaged in a form a small clinic can actually deploy. MediTriage is our test of whether that packaging is possible.
What it does
MediTriage is an AI-assisted, clinician-confirmed patient intake system for walk-in clinics.
Patients can do intake three ways: a step-by-step form, a chat assistant that asks one question at a time, or voice input where they just describe what is wrong. Once intake is done, an LLM analyses their symptoms and suggests an Emergency Severity Index triage level from 1 (Critical) to 5 (Administrative). On the staff dashboard, the clinician sees the AI's reasoning, the red flags it picked up, a short clinical briefing, a differential to consider, and five concrete follow-up questions to ask the patient.
For Level 1 critical patients, the system fires redundant alerts:
- A live dashboard toast
- A simulated ESP32 hardware beacon with a red LED, OLED panel, and two-beep buzzer
- A Telegram backup channel
All three have to be acknowledged.
The non-negotiable design rule is that the AI never acts alone. Every triage level carries an "AI Suggested, Awaiting Clinician Confirmation" tag until a human clinician confirms or overrides it. Every state change writes an audit log entry with a timestamp and the staff member's name.
The home page has a six-step demo path that runs the full loop (intake, queue review, triage confirmation, hardware acknowledgement, care start, integrations) in under three minutes if you want to see it end to end.
How we built it
The whole stack got generated end to end with MeDo across 20+ sessions and roughly 140 prompts. No boilerplate copied in.
Two things made MeDo's multi-turn chat actually useful instead of just impressive.
Schema first. We spent the entire first session getting the Postgres schema right. Once we had visits, queue_assessments, hardware_alerts, and staff_actions locked down, every later prompt could just reference those tables by name and MeDo would produce consistent code across pages. Eight migrations later, every page reads from the same source of truth.
One spec, one feature, one fresh chat. For each major feature we would open a new chat, paste in the relevant schema, and write a tight functional spec covering exact field names, exact state transitions, and exact UI behaviour. Then iterate on the output. Mixing specs together or rewriting the spec halfway through always produced worse code than starting over.
The full prompt history with six representative prompts and their generated outputs lives inside the app at /built-with-medo. Judges can audit the build path directly.
The piece we are proudest of is the structured-LLM triage pipeline in the ai-intake-assistant Edge Function. One prompt to MeDo and it produced a Supabase Edge Function that calls Gemini 2.5 Flash with an ESI-aware system prompt, asks for a typed JSON response with eight specific fields, strips markdown fences, parses, retries once on bad JSON, and falls back to a rule-based assessment if the LLM fails completely. Submit cannot error. That single function is what makes MediTriage feel like a clinical workstation instead of a demo.
Challenges we ran into
Getting clean JSON out of an LLM. Gemini sometimes wraps the response in markdown fences. Sometimes adds a chatty preamble. Sometimes truncates. We solved it with a strip-fence, parse, single retry, then deterministic rule-based fallback pattern. The submit handler literally cannot return an error to a patient.
False positives on the realtime dashboard. Supabase Realtime is fast, but the initial fetch and the subscription start in a race condition that fires "new patient" toasts for rows that already existed when the page loaded. We fixed it with a knownIdsRef Set that gets seeded on the first fetch. Only IDs that arrive after subscription start count as new.
The buzzer would not shut up. Our first implementation re-fired the two-beep every time the Level 1 card re-rendered. We added a beepedFor Set keyed by alert ID so each alert beeps exactly once. The two-short-beep pattern (880 Hz, 150 ms each) is also a deliberate clinical UX choice rather than a continuous alarm. A constant beep in a waiting room becomes background noise within five minutes.
Patient-facing copy under stress. A Level 1 patient seeing "Estimated wait: Immediate" still does not know what to do. We added a red banner on the queue ticket that tells critical patients explicitly to alert staff directly and not wait in line. The AI does its job. The patient still has to know what to do with the result.
Accomplishments that we're proud of
- The whole app got built from prompts. Six pages, eight tables, two Edge Functions, hardware simulator, voice intake, chat assistant.
- The AI's output reads like an actual triage note. Dashboard cards include a clinical briefing, a differential, follow-up questions, and a list of what the AI could not see. A real triage nurse could work from this.
- The human-in-the-loop pattern is enforced everywhere. AI suggestions carry a confirmation tag until a clinician acts. Override is one click. The audit trail names who and when.
- The redundant alert path actually feels redundant. Dashboard, ESP32 beacon, Telegram. The hardware simulator pulses, beeps, and writes a JSON payload that is production-shaped.
What we learned
Spec quality is the bottleneck, not generation quality. When our prompt was sloppy, MeDo's output was sloppy. When we tightened the spec with exact field names and exact state transitions, the output was usable on the first try.
Realtime plus structured LLM output is the combination that matters. Once those two pieces work together, the app stops feeling like a CRUD form and starts feeling like a clinical tool.
Healthcare UX is mostly about what you do not show. The dashboard could surface fifty more fields. Restraint, only the clinically relevant ones, is what makes it trustworthy.
What's next for MediTriage
- Wire up a real ESP32. The payload structure is already production-shaped, so this is a small additional step rather than a rebuild. We are EE students. This part is the fun part.
- EHR write-back. A FHIR-compliant integration so confirmed triage levels flow into the clinical record.
- Pilot with a Nairobi clinic. Swahili language support. An offline-capable PWA for unreliable connectivity. M-Pesa integration for prescription refill workflows.
- Triage outcome tracking. Record what the patient was actually diagnosed with, compare against the AI's differential, and fine-tune the system prompt over time. Close the loop.
AI suggestions are not a diagnosis. All triage levels must be confirmed by a qualified clinician.
Built With
- esp32
- gemini-2.5-flash
- google-gemini
- lucide-icons
- medo
- postgresql
- react
- react-hot-toast
- server-sent-events
- supabase
- supabase-edge-functions
- supabase-realtime
- tailwind-css
- telegram-bot-api
- typescript
- web-audio-api
- web-speech-api
Log in or sign up for Devpost to join the conversation.