Offline-first healthcare continuity platform - patient β doctor, anywhere.
Live: https://continuum-alpha-two.vercel.app
API: https://continuum-a8um.onrender.com
CONTINUUM is a healthcare continuity platform built for patients who see multiple doctors and lose the thread between appointments - and for doctors who spend the first ten minutes of every consultation asking questions that were already answered by someone else.
Patients maintain a single, portable health record: conditions, medications, consultations, lab reports, vitals. They share access with specific doctors. Doctors see the full picture before responding. Everything works offline and syncs when connectivity returns.
- Health timeline - every consultation, condition, medication, document, and vital in one chronological feed
- Async consultations - record symptoms by voice, submit to a connected doctor, receive a response with structured medications and follow-up scheduling
- Document upload - lab reports, scans, and prescriptions attached to your record, compressed client-side before upload
- Vitals tracking - blood pressure, glucose, weight, heart rate with trend charts
- Live calls - scheduled WebRTC video calls with doctors, call audio saved to your timeline automatically
- Offline-first - everything above works without internet; data syncs automatically when back online
- Patient timeline view - full health history before responding to any consultation
- Structured medications - prescribe with dosage, frequency, duration, and instructions; active medications surfaced in the patient's profile
- Condition management - add chronic conditions with severity and status; only doctors can add conditions (not inferred from symptom checkboxes)
- Follow-up scheduling - schedule follow-ups from any consultation response; overdue follow-ups surfaced on the dashboard
- Doctor-initiated check-ins - reach out to chronic patients without waiting for them to submit a consultation
- Analytics - patient count, avg response time, follow-up completion rate, top conditions, call stats; CSV export
- Doctor verification - one-click approve/revoke verified status
- User management - view all users, filter by role, soft-delete accounts
- Storage monitoring - file count and total MB across uploads
continuum/
βββ client/ React + Vite + TypeScript + Tailwind CSS
β βββ PWA vite-plugin-pwa (offline shell, service worker)
β βββ Offline DB Dexie.js (IndexedDB) - sync queue + timeline cache
β βββ Real-time Socket.io client + RTCPeerConnection (WebRTC)
β
βββ server/ Node.js + Express + TypeScript
βββ Database MongoDB Atlas (Mongoose ODM)
βββ Auth JWT (jsonwebtoken + bcryptjs)
βββ Files Multer - audio, images, call recordings
βββ Real-time Socket.io - WebRTC signaling server
βββ i18n Client-side (i18next) - English, Hindi, Telugu
Patient (offline)
βββ Creates consultation βββΊ IndexedDB sync_queue (pending)
βββ Records audio βββββββββββΊ IndexedDB blobs store
βββ Logs vitals βββββββββββββΊ IndexedDB sync_queue (pending)
[connectivity returns]
Sync engine
βββ Upload blobs βββββββββββΊ Express β /uploads/audio/
βββ POST records βββββββββββΊ Express β MongoDB
βββ Mark synced ββββββββββββΊ IndexedDB update
βββ Pull fresh data ββββββββΊ Update IndexedDB cache
Conflict resolution: client sends updatedAt, server rejects stale writes with HTTP 409. User sees a non-blocking notification - no silent data loss.
Patient Signaling (Socket.io) Doctor
βββ join_room βββββββββββββββββββββββββββββββββββββββββΊβ
ββββββββββββββββββββ peer_joined ββββββββββββββββββββββ€
βββ sdp_offer (forwarded) ββββββββββββββββββββββββββββΊβ
ββββββββββββββββ sdp_answer (forwarded) βββββββββββββββ€
ββββββββββββββββ P2P audio + video ββββββββββββββββββββΊβ
β
[call ends]
βββ Patient's device stops MediaRecorder
βββ Uploads audio blob to server
βββ Server creates LIVE_CALL consultation β appears on timeline
| Layer | Technology |
|---|---|
| Frontend | React 18, Vite, TypeScript, Tailwind CSS |
| Offline storage | Dexie.js (IndexedDB wrapper) |
| PWA | vite-plugin-pwa |
| Real-time | Socket.io client, RTCPeerConnection |
| i18n | i18next, react-i18next, i18next-browser-languagedetector |
| Backend | Node.js, Express, TypeScript |
| Database | MongoDB Atlas (Mongoose) |
| Auth | JWT (jsonwebtoken), bcryptjs |
| File upload | Multer |
| Signaling | Socket.io (same Express server, same port) |
| TURN | Xirsys (NAT traversal for WebRTC) |
| Frontend hosting | Vercel |
| Backend hosting | Render |
- Node.js 20+
- npm
- MongoDB Atlas account (free M0 cluster)
- Git
git clone https://github.com/your-username/continuum.git
cd continuum
# Install server dependencies
cd server && npm install
# Install client dependencies
cd ../client && npm installcd server
cp .env.example .envEdit .env:
MONGODB_URI=mongodb+srv://<user>:<password>@cluster.mongodb.net/continuum
JWT_SECRET=<generate with: node -e "console.log(require('crypto').randomBytes(64).toString('hex'))">
PORT=3001
CLIENT_ORIGIN=http://localhost:5173
# Optional - TURN server for WebRTC NAT traversal
# Without these, calls work on the same network but may fail on mobile data
XIRSYS_IDENT=
XIRSYS_SECRET=
XIRSYS_CHANNEL=Create client/.env:
VITE_API_ORIGIN=http://localhost:3001# Terminal 1 - server
cd server && npm run dev
# Terminal 2 - client
cd client && npm run devClient runs at http://localhost:5173, server at http://localhost:3001.
Admin accounts cannot be self-registered by design (prevents privilege escalation). To create one:
- Register normally as a patient
- Open MongoDB Atlas β Collections β
users - Find your document, change
role: "PATIENT"torole: "ADMIN" - Log out and log back in
| Setting | Value |
|---|---|
| Root directory | server |
| Build command | npm install && npm run build |
| Start command | npm start |
| Environment | Node |
Add all .env variables in Render's Environment tab. CLIENT_ORIGIN must match your Vercel URL exactly, no trailing slash.
Note: Render's free tier sleeps after 15 minutes of inactivity. The first request after sleep takes ~30 seconds. WebRTC calls will fail if the signaling server is cold - upgrade to a paid instance before live use.
| Setting | Value |
|---|---|
| Root directory | client |
| Framework preset | Vite |
| Build command | npm run build |
| Output directory | dist |
Add VITE_API_ORIGIN=https://continuum-a8um.onrender.com in Vercel's Environment Variables.
Note: Uploaded files (audio, documents, call recordings) are stored on Render's ephemeral filesystem and are lost on every redeploy. For production use, replace the local Multer storage with Cloudflare R2 or AWS S3.
- Open Chrome DevTools β Network β Offline
- Register as a patient, complete health profile, submit a consultation with audio
- Check Application β IndexedDB β
continuum_dbβsync_queue- pending items should appear - Set network back to Online
- The sync engine fires automatically on the
onlineevent - Verify records in MongoDB Atlas β Collections
continuum/
βββ client/
β βββ src/
β βββ components/
β β βββ consultation/ AudioRecorder, AudioPlayer, SymptomChecklist
β β βββ documents/ DocumentUploadButton
β β βββ followups/ FollowUpsList
β β βββ medication/ SpeakMedicationButton (TTS)
β β βββ sync/ SyncStatusWidget, SyncErrorPanel
β β βββ timeline/ TimelineEntryRow, HealthSummaryCard, AddConditionForm
β β βββ ui/ GlassCard, Avatar, StatusPill, Navbar, LanguageSwitcher
β β βββ vitals/ VitalsLogForm, VitalsChart
β βββ lib/
β β βββ apiClient.ts Axios + JWT injection
β β βββ authContext.tsx Auth state
β β βββ callRecorder.ts MediaRecorder for live calls
β β βββ compressImage.ts Canvas-based image compression
β β βββ i18n.ts i18next setup
β β βββ offlineDB.ts Dexie schema (v3)
β β βββ resolveFileUrl.ts Server-relative β full URL
β β βββ socket.ts Socket.io singleton
β β βββ syncEngine.ts Offline queue + retry logic
β β βββ useAudioRecorder.ts MediaRecorder hook
β β βββ useTextToSpeech.ts Web Speech API hook
β β βββ webrtc.ts RTCPeerConnection wrapper
β βββ locales/
β β βββ en/common.json
β β βββ hi/common.json
β β βββ te/common.json
β βββ pages/
β βββ admin/ AdminDashboard
β βββ auth/ LoginPage, RegisterPage
β βββ call/ ScheduleCallPage, CallRoomPage
β βββ doctor/ DoctorDashboard, ConsultationDetailPage, AnalyticsPage, MyPatientsSearchPage
β βββ patient/ PatientDashboard, TimelinePage, OnboardingPage, NewConsultationPage,
β ConsultationListPage, DoctorSearchPage, MyDoctorsPage, ProfilePage
β
βββ server/
βββ src/
βββ lib/
β βββ db.ts MongoDB connection
β βββ expiryCron.ts Auto-expires stale connection requests
βββ middleware/
β βββ auth.ts JWT verification + role guard
β βββ auditTrail.ts Patient change logging
β βββ patientAccess.ts assertPatientAccess() - core access control
β βββ upload.ts Multer - async audio
β βββ uploadImage.ts Multer - documents
β βββ uploadCallRecording.ts Multer - call recordings
βββ models/
β βββ Call.ts
β βββ Condition.ts
β βββ Consultation.ts
β βββ Document.ts
β βββ DoctorProfile.ts
β βββ FollowUp.ts
β βββ Medication.ts
β βββ PatientChange.ts
β βββ PatientDoctorLink.ts
β βββ PatientProfile.ts
β βββ User.ts
β βββ Vital.ts
βββ routes/
β βββ admin.ts
β βββ analytics.ts
β βββ auth.ts
β βββ calls.ts
β βββ conditions.ts
β βββ connections.ts
β βββ consultations.ts
β βββ documents.ts
β βββ doctors.ts
β βββ followups.ts
β βββ patients.ts
β βββ timeline.ts
β βββ vitals.ts
βββ socket/
β βββ signaling.ts Socket.io WebRTC signaling handlers
βββ index.ts Express + Socket.io server bootstrap
- Persistent file storage - migrate audio, documents, and call recordings from local filesystem to Cloudflare R2 or AWS S3 for durability across deployments
- Full i18n coverage - extend Hindi and Telugu translations across all pages and components (currently covers Navbar and Patient Dashboard)
- SMS / WhatsApp notifications - notify patients of doctor responses and upcoming follow-ups via Twilio when the app is not open
- Family health management - allow a single account to manage health records for dependents (children, elderly parents)
- Diagnostic center integration - allow labs and imaging centers to upload reports directly to a patient's record without going through the patient manually
- Medication reminders - push notifications or SMS reminders when a medication dose is due, based on prescribed frequency
- Doctor availability calendar - let doctors set available slots for live calls so patients can self-schedule without back-and-forth
- Population health analytics - village-level or region-level disease trend dashboards for public health administrators, built on anonymised aggregated data
- AI-assisted symptom triage - surface relevant past consultations and conditions when a patient submits symptoms, helping doctors respond faster
- Multi-language voice input - extend audio symptom recording with speech-to-text transcription in Hindi and Telugu so doctors can read symptoms without listening to full recordings
MIT