Skip to content
Selected work

MedPal Provider · MedPal

Real-time consultations, and 480 keys that refuse to drift

Provider-side telemedicine: video and voice consults on Agora, payouts, availability, and a bilingual product where the second language stays correct because CI won’t let it rot.

Role
Flutter Engineer
Organisation
MedPal
Period
2025 - present
Surface
Flutter
01

The problem

A consultation isn’t a screen, it’s a lifecycle: a request arrives, a provider accepts, a call runs with controls, and it ends, sometimes cleanly, often not, occasionally on a train.

The platform ships into an English- and Spanish-speaking market, and internationalisation done once decays from the very next pull request unless something enforces it.

02

Constraints

  • Real-time media has failure modes the rest of the app doesn’t: a dropped call needs a defined destination, not an undefined one.
  • Healthcare context: an AI suggestion that routes a patient wrongly is not a cosmetic bug.
  • Multiple Firebase environments (dev, staging, prod) behind build flavours.
  • 480+ user-facing strings, and a team that will keep adding more.
03

Decisions

01

Make the consultation lifecycle explicit

Incoming request, accept, in-call controls and completion are modelled as states around the Agora RTC engine, on a Clean Architecture core with Cubit, go_router and get_it. Every terminal state, including “the network went away”, resolves somewhere specific.

What I rejected

Driving the call from widget state and SDK callbacks directly. It works in a demo and produces a UI that can’t say what’s happening the first time a consult drops at minute nine.

02

Make translation drift a build failure

All 480+ strings migrated to gen-l10n, with CI parity tests that fail when one locale gains a key the other doesn’t.

What I rejected

A translation checklist enforced in code review. Reviewers catch the first ten misses and none of the next hundred, and six months later the Spanish build is a patchwork.

03

Use the model where it removes a form, not where it removes a decision

Firebase AI (Vertex AI / Gemini) suggests a provider’s medical specialty during onboarding. The provider confirms it. Nothing clinical is inferred and committed without a human in the loop.

What I rejected

Letting the model classify and persist directly. It’s a better demo and a worse product: in healthcare a mis-set specialty is a routing error with a patient on the other end of it.

04

Where it landed

  • Live provider-to-patient video and voice consults, earnings and payouts, availability scheduling, QR generation, biometric login and consent capture.
  • A genuinely bilingual codebase where adding an English string without its Spanish counterpart breaks the build.
  • Flutter
  • Agora RTC
  • Firebase AI (Vertex / Gemini)
  • Cubit / flutter_bloc
  • go_router
  • get_it
  • gen-l10n

Working on something like this?

I’m open to senior mobile and full-stack roles, and I’m relocation-ready.

donaldamadi15@gmail.com