Inspiration
We kept coming back to the same frustrating experience: you feel sick on a Tuesday, the first appointment is Friday, and by the time you're in the room you're trying to remember a week of symptoms in ten minutes while the doctor figures out how urgent you are from almost nothing. Canadian primary care is stretched thin, and the system loses information in three places: symptoms go uncaptured between when they happen and the visit, patients reconstruct them from memory, and the queue is ordered by who booked first instead of who is sickest. We wanted to close those gaps without asking clinics to rip out the systems they already use.
What it does
MedSimple lets a patient report symptoms the moment they happen, by text, voice, or photo. AI does a fast first pass: it writes a plain-language clinical summary and assigns an urgency level (Routine, See soon, Urgent, Emergency). The physician console then shows a queue sorted sickest-first, and the doctor stays in control of everything: they confirm or override the AI's urgency (with a logged reason), approve or rewrite the AI-drafted care plan, and sign every prescription only after an automatic allergy, interaction, and dose check. From one screen the physician runs the whole loop: prescriptions, lab requisitions, specialist referrals, results with a release gate, appointments, and two-way follow-up messaging. Every external integration has a printable fallback, so a clinic with no infrastructure can use it on day one. If a patient reports a red flag like chest pain, the app skips the queue and tells them to call 911.
How we built it
The backend is Java 17 and Spring Boot 4, modeled on FHIR R4 so every clinical entity maps to a real healthcare standard. AI runs through Spring AI against OpenAI GPT-4o (triage and summaries), GPT-4 Vision (the photo-relevance gate), and Whisper, with Valsea.ai added for voice transcription. The data lives in PostgreSQL on Supabase's Canadian region for residency. The frontend is React 19, TypeScript, Vite, Tailwind, and Curson for development.
The core architectural idea is the adapter pattern: every external capability, AI or integration, sits behind an interface with two implementations, a real one and a deterministic fallback, chosen by config at runtime. That is what makes the whole app work with zero infrastructure and lets us swap an AI provider without touching business logic. We backed it with two test lanes: fast deterministic gate tests (436 passing) and LLM-as-judge eval suites with hard safety floors.
Challenges we ran into
Building for Canadian health privacy (PHIPA and PIPEDA) from the start shaped everything. We use a US AI provider, so we strip every patient identifier (names, health-card numbers, phone, email, postal code) before any text reaches a model. Getting the fallback-first design right meant every workflow had to complete end to end even with all integrations off.
The adapter wiring bit us in an instructive way: a single config property originally selected both voice and photo AI, so when we added valsea for voice it would have orphaned the photo bean and crashed startup. We had to decouple the selector cleanly. The valsea integration itself was a debugging lesson: it returned a clear error until we sent the required language field, the browser records webm rather than wav, and a stale process holding port 8080 made it look like our fix wasn't loading. And because AI output is nondeterministic, we couldn't rely on normal tests for quality, so we built an eval harness instead.
Accomplishments that we're proud of:
We have the full loop working end to end, on fallback rails, today: multimodal intake, AI triage, physician confirmation, care plans, prescriptions with safety checks, diagnostics with release-gated results, referrals, appointments, follow-ups, notifications, and wearable vitals. The photo-relevance gate is a favorite: junk images never reach a doctor as a fake finding, but real symptoms flow straight through. The human-in-the-loop design with logged overrides, the FHIR-first data model, and the PHIPA foundations (Canadian residency, encryption of health-card numbers, append-only consent and audit logs, result-release gating) make it feel like a real pilot product, not a hackathon mock. And the adapter pattern proved itself: we added a whole new transcription provider as essentially a config change.
What we learned
The biggest lesson was splitting work into the right space: use the AI for judgment and pattern matching, and use plain deterministic code for anything that should give the same answer every time, then guard the AI with evals instead of hoping. We learned that PHIPA compliance is not just encryption; the harder parts are access control (circle of care) and patient data rights, and that being honest about what is built versus designed-and-sequenced earns more trust than overclaiming. Scoping to Ontario only, instead of "Canada-ready," made the whole project sharper. And designing every integration behind an interface from day one is what let us move fast without breaking the parts that already worked.
What's next for MedSimple
Wire the live rails: PrescribeIT e-prescribing, Ocean eReferral, lab networks, and EMR connectivity over FHIR, which are scaffolded behind toggles and currently use the printable fallback.
Real identity and credentials: live CPSO physician verification and Ontario Health Card validation, both currently stubbed.
Finish the privacy layer: circle-of-care access control, read auditing, and secure patient self-export (the PHIPA right of access), before any real patient data.
Grow carefully: province by province, each with its own privacy rules, then evaluate the US and HIPAA.
Our own model (Phase 3): every physician confirm/override is a labeled data point, so on consented de-identified data we can fine-tune an open model and host it in Canada for full data residency, pursued alongside medical-device licensing.
Built With
- cursor
- docker
- fhir
- flyway
- gpt-4o
- hapi-fhir
- java
- junit
- jwt
- maven
- openai
- postgresql
- react
- react-query
- react-router
- spring-ai
- spring-boot
- spring-security
- supabase
- tailwindcss
- testcontainers
- typescript
- valsea.ai
- vite
- whisper
Log in or sign up for Devpost to join the conversation.