MedCore is a centralised digital health records platform for African healthcare providers — a Vite + React PWAfront-end with aNode + Express + SQLite (libSQL) API. It implements the PRD's eight features end-to-end with FHIR-shaped resources, RBAC-gated access, and an AI assist layer that summarises patient context and surfaces risk flags. Every external integration (Daily.co, OpenAI Whisper, Africa's Talking, OpenFDA, Web Push) ships with a working mock so the demo runs offline.
Winner — Yale Africa Innovation Symposium IV (April 16–18, 2026), built within the Technology & AI Innovation Lab track under the symposium's "The Pulse of Progress" theme.
![]() |
![]() |
| Final presentation, Yale, April 18, 2026 | Technology & AI Innovation Lab participants, YAIS IV |
git clone https://github.com/Builder106/med-core.git
cd MedCore
npm install
npm --prefix server install
npm run devThe Vite dev server proxies /api/*to the Express server on port 3001 and binds to0.0.0.0, so a phone on the same Wi-Fi can open http://<laptop-ip>:5173.
| Role | User ID | Default PIN |
|---|---|---|
| Doctor | DOC-001 |
4242 |
| Patient | PAT-001 |
1212 |
| Admin | ADM-001 |
3434 |
PINs are configurable in server/.env(seeserver/.env.example). For production, set SESSION_SECRET to a long random string (≥32 characters). If a login fails after editing PINs, restart the API to resync demo PINs — dev does this on every start.
The doctor opens a chart through a session-guarded API call; SQLite returns patient, medication, lab, and encounter data. An optional summary request sends patient context to the AI layer and returns a summary with risk flags. For a prescription, OpenFDA returns a critical, warning, or no-interaction result. A critical result without acknowledgement returns 409 and asks for a PIN; an acknowledged or noncritical request is written with an audit record and returns 201, then the chart updates. Edit the chart, summary, interaction check, or outcome diagram.
All external integrations fall back to mocks when API keys are absent, so the canonical journey above works offline.
Core workflow — doctor signs in, opens a patient chart, AI panel auto-loads (≈25s)
Recorded against the live deploy at https://api.yinkavaughan.me via the e2e/demo/features/01-core.feature Gherkin scenario.
How to regenerate / add more
The Gherkin suite at e2e/demo/features/ drives Playwright with slowmo + a custom video reporter that converts webm → mp4 → gif. Add a 0N-<name>.feature and:
npx playwright install chromium # one-time
E2E_BASE_URL=https://api.yinkavaughan.me DEMO=1 npm run e2e:demo # records mp4
npm run e2e:demo:gif # mp4 -> gif (10 fps, 960px wide)
cp e2e/demo-videos/<slug>.gif assets/<name>.gifThe full mechanics — cursor injection, dwell helpers, the 0-byte first-test workaround — are documented in docs/E2E.md.
See docs/DEMO.md for the full phone walkthrough (PWA install, voice, video, push reminders, SMS, Health ID QR, offline/low-bandwidth).
Media APIs (camera, microphone, push) require a secure context:
# Option 1 — tunnel (recommended for dev)
cloudflared tunnel --url http://localhost:5173 # brew install cloudflared
# or
ngrok http 5173
# Option 2 — light cloud deploy (Fly.io / Railway / Render)
docker build -t medcore .For the Africa's Talking SMS callback, point the inbound webhook at https://<your-public-url>/api/sms/inboundand sendPATIENT PAT-001 PIN:4242from the phone number set asDEMO_DOCTOR_PHONEinserver/.env.
npm test # web (Vitest)
npm --prefix server test # API + SMS + interaction + FHIR + integrations
npm --prefix server run typecheck
npm run test:all # web + serverCI runs all of the above on every PR — see .github/workflows/ci.yml.
| File | Contents |
|---|---|
docs/PRD.md |
Full product requirements document |
docs/DEMO.md |
Phone walkthrough for all 8 features |
docs/ENV_SETUP.md |
Guide to filling out server/.env |
docs/go-to-market.md |
GTM strategy and pilot roadmap |
docs/GUIDELINES.md |
Development conventions |
docs/ATTRIBUTIONS.md |
Third-party licenses and credits |
CONTRIBUTING.md |
Dev setup, project guardrails, PR convention |
Copy server/.env.exampletoserver/.env and fill in only the integrations you need:
| Variable | Purpose | Fallback when empty |
|---|---|---|
OPENROUTER_API_KEY |
AI summaries and risk flags | Returns a deterministic mock summary |
GROQ_API_KEY/OPENAI_API_KEY |
Whisper transcription (F2) | Returns realistic mock transcripts |
DAILY_API_KEY/DAILY_DOMAIN |
Video rooms (F3) | Falls back to a public Jitsi room |
AT_API_KEY |
SMS send (F4 & F5) | Logs to a mock outbox |
WEB_PUSH_PUBLIC_KEY/WEB_PUSH_PRIVATE_KEY |
Push reminders (F5) | In-memory fake send |
DATABASE_ENCRYPTION_KEY |
AES-256-GCM PII column encryption | Disabled (plaintext) — set before real PII |
DEMO_DOCTOR_PHONE/DEMO_PATIENT_PHONE |
Route SMS / reminders to your real number | — |
Generate VAPID keys: npx web-push generate-vapid-keys. Generate an encryption key: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))".
- Multilingual (i18next, 5 languages + RTL Arabic) —
src/locales/ - Voice recording + AI transcription —
src/app/components/clinical/VoiceConsultPanel.tsxandserver/src/routes/voice.ts - Video consulting (Daily.co + Jitsi fallback) —
src/app/pages/VideoConsultPage.tsxandserver/src/routes/video.ts - SMS offline system —
server/src/routes/sms.ts+ doctor inbox atsrc/app/pages/SmsInboxPage.tsx - Medication reminders + adherence —
server/src/routes/reminders.ts+ doctor/patient UIs - Drug interaction checker —
server/src/routes/interactions.ts+server/src/routes/prescriptions.tswith PIN override - EHR domain — appointments, labs, vaccinations, referrals, encounters, inventory, staff, consent, audit —
server/src/routes/* - AI assist + FHIR export —
server/src/routes/ai.ts,server/src/routes/fhir.ts,server/src/lib/fhir-mappers.ts
docker compose up -d postgres
# then set DATABASE_URL in server/.env to a Postgres URL
The SQLite schema in server/src/db/migrations.sql is portable; switching dialects only requires updating the Drizzle client.
PRs welcome. See CONTRIBUTING.md for dev setup, project guardrails (PHI safety, offline-first, mock-friendly integrations, RBAC), commit convention, and the out-of-scope list. CI must stay green.
MedCore is released under the MIT License. © 2026 Yinka Vaughan.
Third-party licenses and asset attributions are tracked in docs/ATTRIBUTIONS.md.






