Skip to content
Rakibul Hasan Dihan
Back to projects

Case Study

Mediflow

An AI-powered healthcare & telemedicine platform built the way real distributed systems are built.

Mediflow logo

Overview

Problem Statement

Access to care is slow and fragmented — waiting rooms, scattered paper records, and no easy way to get quick guidance between visits.

Solution

Mediflow connects patients and doctors for virtual care: on-demand video consultations, an AI assistant for general guidance, automatic prescription digitization, and a single dashboard to track health records. Doctors get a verified onboarding flow, a scheduling dashboard, and a clinical AI assistant that can pull a patient's real medical history live during a conversation — with the visit automatically transcribed so nothing gets lost.

Architecture Overview

Mediflow is composed of seven independently deployable services sharing one Firebase project as the single source of truth. Every service verifies caller identity independently via the Firebase Admin SDK — there is no central session store, and no service trusts another service's prior check. Firestore's real-time listeners double as the event/pub-sub layer, coordinating call status and cross-service state without a message broker.

Features

1

Search doctors by specialty with live appointment slot availability

2

One-click video/audio consultations, no downloads

3

"Medora" AI health assistant with safety guardrails and emergency escalation

4

Prescription upload with automatic client-side OCR digitization

5

Fitness and recovery tracking (workouts, diet, macros)

6

Centralized health records dashboard

7

Doctor onboarding with document upload and admin approval

8

Doctor-facing Medora AI assistant with MCP tool-calling into real patient records

9

Automatic call transcription in free or high-accuracy Whisper mode, visible only to the doctor

Architecture Diagrams

01

System Architecture

  • Patient and Provider frontends (Next.js / React+Vite) talk to five independently deployable backend services over REST, each authenticated with a Firebase ID token.
  • Patient Backend (:5000), Provider Backend (:5001), Call Service (:4000), AI Gateway (:5003), and MCP Server (:5002) all read and write through one shared Firestore instance — the single source of truth.
  • Cloudinary handles media storage, LiveKit Cloud powers video calls, and Firebase Cloud Messaging delivers push notifications as supporting infrastructure around the core services.
02

Authentication Flow

  • The client signs in via Firebase Auth and attaches the resulting ID token to every API request.
  • Each backend service independently verifies that token with the Firebase Admin SDK before processing the request.
  • No central session store, and no service trusts another service's prior check — invalid or expired tokens are rejected at every boundary, not just the first one.
03

Video Call Sequence

  • The doctor starts the call from the appointment dashboard; the Call Service verifies ownership of that appointment before doing anything else.
  • A LiveKit room scoped to the appointment is created (capped at 2 participants), and Firestore's call status flips to active in real time.
  • The patient's frontend picks up the status change instantly via a Firestore listener and joins with its own scoped access token — no polling involved.
04

AI Gateway Internals

  • One AI Gateway service fronts three interchangeable LLM providers — Claude, Gemini, and OpenRouter/GPT — selected per deployment via environment variable.
  • Patient-facing chat is intentionally limited to general guidance, with safety guardrails that detect emergency language and escalate.
  • Doctor-facing chat gets access to real data tools via MCP — the same Gateway code path branches based on who's asking.
05

MCP Tool-Calling Flow

  • When the doctor's AI assistant decides it needs patient data (e.g. current medications), the AI Gateway calls the MCP Server with the doctor's own ID token attached.
  • The MCP Server independently re-verifies that token — even though the Gateway already checked it — before touching Firestore.
  • Tool results flow back through the same provider adapter and into the model's final answer, streamed to the doctor in real time.
06

Call Transcript Flow

  • Free mode: each participant's browser transcribes its own audio locally via the Web Speech API, and segments are merged by timestamp after the call.
  • Accurate mode: the doctor's browser mixes local and remote audio into a single stream, uploads it, and the AI Gateway transcribes it with OpenAI Whisper.
  • Either way, the finished transcript is saved to the patient's chart and is visible only to the doctor.
07

Target Architecture at 1M Users

  • At roughly 1M registered users (~10K peak concurrent), a CDN handles static assets/media and a new API Gateway / Load Balancer sits in front of every autoscaled service.
  • A new Redis cache absorbs hot reads (directories, appointment slots), and a new pub/sub message queue offloads transcript-merge and AI-analysis jobs to async workers instead of running them inline.
  • Firestore moves to sharded counters and event-based writes, LiveKit Cloud auto-scales its SFU media servers, and the MCP Server gets automatic failover across Claude, Gemini, and OpenRouter.

Implementation Workflows

Authentication
  1. User signs in via Firebase Auth (Google OAuth) on either frontend.
  2. Firebase returns a signed ID token to the client.
  3. The client attaches the token to every API request.
  4. Each backend service independently verifies the token with the Firebase Admin SDK before processing the request.
  5. Invalid or expired tokens return 401 at the service boundary — no service trusts another service's prior check.
Appointment Booking
  1. Patient completes a fitness profile — a required gate before booking is unlocked.
  2. Patient picks a specialty, doctor, consultation type (video/phone), date, and time slot.
  3. Available slots are computed live: provider working hours minus already-booked slots, with past slots filtered out.
  4. Booking is written to Firestore's shared appointments collection — the same collection the provider dashboard reads from.
  5. Provider sees the new appointment appear in real time via Firestore listeners, with no polling.
Video Consultation
  1. Doctor starts the call from the appointment dashboard.
  2. Call Service verifies the doctor owns that appointment, creates a LiveKit room scoped to that appointment (capped at 2 participants), and mints a scoped access token.
  3. Firestore call status flips to active — the patient's frontend picks this up instantly via a real-time listener.
  4. Patient joins and receives their own scoped token from the Call Service.
  5. Either side can end the call; call status flips to ended and is enforced server-side against appointment ownership.
AI Assistant & MCP Tool-Calling
  1. Chat request hits the AI Gateway, which routes to one of three interchangeable LLM providers (Claude, Gemini, or OpenRouter/GPT), selected per deployment via environment variable.
  2. Patient chat is general guidance only — no data tools are exposed, and safety guardrails detect emergency language and escalate.
  3. Doctor chat gives the model a set of MCP tools (e.g. get current medications, get diagnoses); if the model decides a tool is needed, the AI Gateway calls the MCP Server with the doctor's ID token.
  4. The MCP Server independently re-verifies that token — even though the Gateway already checked it — before querying Firestore.
  5. Tool results flow back through the same provider-specific adapter and into the model's final answer, streamed to the doctor.
Call Transcription
  1. Free mode: each participant's browser transcribes its own audio locally via the Web Speech API; segments are merged by timestamp after the call.
  2. Accurate mode: the doctor's browser mixes local and remote audio into one stream via the Web Audio API, uploads it, and the AI Gateway transcribes it with OpenAI Whisper.
  3. Either way, the final transcript is saved to the patient's chart and is visible only to the doctor.
Prescription OCR
  1. Patient uploads a photo of a prescription.
  2. Text extraction runs client-side with Tesseract.js — no server round-trip for the initial read.
  3. Structured data (medicine names, dosage) is submitted to the backend and stored under the patient's prescriptions subcollection, tagged by source.

Technology Stack

Patient Backend

Node.jsNode.js/Express (ESM)FirebaseFirebase AdminCloudinaryCloudinaryOpenAI SDK

Patient Frontend

Next.jsNext.js 15 (App Router)ReactReact 19TypeScriptTypeScriptTailwind CSSTailwind CSSAnt DesignAnt Design

Provider Backend

Node.jsNode.js/Express (ESM)FirebaseFirebase AdminCloudinaryCloudinaryMulter

Provider Frontend

ReactReact 18ViteViteTypeScriptTypeScriptReact RouterReact RouterTailwind CSSTailwind CSS

Call Service

Node.jsNode.js/ExpressLiveKitLiveKit Server SDKFirebaseFirebase Admin

AI Gateway

Node.jsNode.js/ExpressAnthropicAnthropic SDKGoogle GeminiGoogle GenAI SDKOpenAI SDKFirebaseFirebase Admin

MCP Server

Node.jsNode.js/ExpressModel Context Protocol SDKFirebaseFirebase Admin

Shared Infrastructure

FirebaseFirebase AuthFirebaseFirestoreFirebaseFirebase StorageLiveKitLiveKit CloudFirebaseFirebase Cloud MessagingTesseract.jsOpenAI Whisper

CI/CD Pipeline

  1. Lint & type-check on every push and PR
  2. Build (next build / vite build / plain Node per service)
  3. Run each service's test suite
  4. Deploy a PR preview environment for review
  5. On merge to main: frontends to Vercel, backends to Render/Cloud Run, Firestore rules/indexes via Firebase CLI
  6. Isolated dev/staging/production Firebase projects

Case Studies

The Patient With No Time to Wait

Sarah feels unwell but can't get a same-day GP appointment. She opens Mediflow, describes her symptoms to Medora, the AI health assistant, and gets general guidance plus a recommendation to see a doctor. She books a same-day video consultation with an available specialist in under a minute. During the call, her doctor pulls up her medication history instantly via the MCP-powered clinical assistant instead of asking her to repeat it.

The Doctor Who Never Loses Context

Dr. Ahmed sees a returning patient. Before the call even starts, he asks the doctor-facing AI assistant for a quick summary of the patient's diagnoses and current medications — the assistant queries real Firestore data live via MCP tools, not a stale cached summary. After the visit, the call is automatically transcribed and saved to the patient's chart.

Digitizing a Decade of Paper Prescriptions

A patient with years of paper prescriptions photographs each one. Mediflow's client-side OCR extracts medicine names and dosages directly in the browser, turning unreadable handwriting photos into structured, searchable records without ever uploading the raw image for that first pass.

Engineering Highlights

  • Multi-LLM provider abstraction — Claude, Gemini, and OpenRouter are interchangeable behind one adapter layer; adding a new LLM provider doesn't touch business logic.
  • Hard patient/doctor AI boundary — the patient chat has zero data-tool access; the doctor chat does, via MCP. This is an architectural boundary, not a prompt-level rule.
  • Defense-in-depth authentication — every service re-verifies the caller's identity independently, including the MCP server re-checking a token the Gateway already validated.
  • Firestore as the event layer — real-time listeners handle call status and cross-service coordination without a message broker.
  • Dual-mode transcription — a free, fully client-side mode and a higher-accuracy server-side Whisper mode, selectable per call.
  • Deliberately simple today, scalable by design — no premature infrastructure (cache, queue, gateway), with a documented path to add each once real load justifies it.