Speech
Jul 31, 2026 · 8 min read · 0 views
The Care Nexus
AI-assisted healthcare SaaS platform
The Care Nexus is an AI-powered, voice-enabled healthcare management platform designed to digitize and centralize clinical workflows for independent doctors, private clinics, and patients. The Care Nexus follows a hybrid SaaS-based architecture, supporting both standalone doctors and multi-doctor clinics, making it scalable, modular, and suitable for real-world healthcare environments.
- Timeline
- 2026-03 - 2026-07
- Origin
- Original — own idea, self-directed
- Role
- Final year project, team of six. I wrote the software.
Overview
The Care Nexus is an AI-powered, voice-enabled healthcare management platform designed to digitize and centralize clinical workflows for independent doctors, private clinics, and patients.
The system addresses critical healthcare challenges prevalent in Pakistan and similar developing regions, including fragmented medical records, handwritten prescriptions, lack of clinic-level analytics, inefficient appointment handling, and poor patient follow-up mechanisms.
By leveraging modern technologies such as Next.js, Node.js, MongoDB, Redis, Whisper API, and OpenAI/Gemini, the platform enables doctors to generate prescriptions using voice, clinics to monitor operational and performance analytics in real time, and patients to maintain lifelong digital medical histories with controlled access.
The Care Nexus follows a hybrid SaaS-based architecture, supporting both standalone doctors and multi-doctor clinics, making it scalable, modular, and suitable for real-world healthcare environments.
Problem
Problems to solve
Paper-based documentation
Doctors spend consultation time writing prescriptions and notes by hand instead of keeping their attention on the patient.
Fragmented medical history
Patient history can remain in paper records that may not be available at the next visit.
Limited clinic visibility
Without an operational view, clinic staff lack a clear basis for understanding appointments, staffing, and revenue.
Disconnected follow-up
After a visit, follow-up depends on the patient remembering rather than on a continuing record and workflow.
The project focuses on the record-keeping and operational gaps that follow when a clinic's core work remains on paper.
Goals
Goals for the build
- Get documentation off paper
Prescriptions generated by speaking, structured well enough to store and search rather than as a wall of transcribed text.
- One record that persists
A medical history that accumulates across visits and belongs to the patient, including records they manage for family members.
- Bilingual, properly
English and Urdu across the whole interface, with right-to-left layout and typography that suits Nastaliq rather than Latin text stretched sideways.
- Operational visibility
Appointment, staff, and revenue figures for clinic administrators, computed rather than estimated.
- Appointment coordination
Patients and clinics need appointments, schedules, and follow-up information to remain connected to the shared record.
- Safe structured assistance
Doctors need voice input and structured prescription fields that reject invalid output rather than saving an incomplete prescription.
The goals connect clinical documentation, patient continuity, language access, and safe clinic operations.
Tech stack
Language model
Frontend
Client state
Backend
Database
Token store
Real-time
Architecture
Technologies I work with day to day, from the frontend through the backend to deployment.
Features
Patient
13 features
Manage personal and medical profile
Search clinics and doctors
Filter doctors by specialization
Book, cancel, or reschedule appointments based on doctor availability
View upcoming, past, and completed appointments
Access prescriptions, lab reports, and medical records
Download and share medical records
Maintain medical history across visits
Manage medical records for family members
Chat with doctors in real time
Receive appointment and follow-up reminders
Use AI health assistant when doctors are unavailable
Use the interface in English or Urdu
Doctor
11 features
Manage doctor profile, specialization, and availability
View upcoming appointments and manage the schedule and queue
Accept, reject, cancel, or complete appointments
Manage patient lists with complete medical history
Generate prescriptions using voice input
Convert speech to text using AI
Add diagnosis, notes, and follow-up instructions
Upload and view patient lab reports
View patient medical history with permission-based access
Chat with patients in real time
Track revenue and earnings
Clinic
7 features
Manage clinic profile and settings
Manage doctors and staff within the clinic
Add or remove doctors from the clinic
View and manage doctor schedules and availability
View clinic revenue and performance analytics
Track doctor activity and clinic performance
Manage clinic-level notification preferences
System
10 features
User registration for Super Admin, Clinic Admin, Doctor, and Patient
Secure login and logout
JWT-based authentication with refresh tokens
Role-Based Access Control (RBAC)
Permission-based access to patient medical history
Profile management for personal information, specialization, and images
Account activation and deactivation
Super Admin access across individual clinics
Scheduled analytics snapshots for faster dashboard access
Notification preferences managed per user
API design
AI
Three controllers, and the split is the point. Prescription parsing is deliberately separate from the chat assistant: they use different providers, different prompts, and, critically, different failure behaviour. The assistant may return prose. The parser may not.
- Parse PrescriptionPOST
/api/ai/parse-prescriptiontranscript in, JSON out
- Parse with GroqPOST
/api/ai/groqstructured completion
- Use Gemini AssistantPOST
/api/ai/geminihealth assistant
Role-scoped resources
Controllers are organised by role first and resource second: doctor/appointment and patient/appointments are different files, not one handler branching on who called it. It duplicates some shape, and it means an authorisation mistake is contained to one role rather than leaking across all of them.
- PatientsGET
/api/doctor/patients - Manage PrescriptionPOST
/api/doctor/prescription - ScheduleGET
/api/doctor/schedule - RecordsGET
/api/patient/records - Manage FamilyPOST
/api/patient/family - View AnalyticsGET
/api/clinic/analytics - StaffPOST
/api/clinic/staff
Auth
Refresh tokens are stored server-side rather than only signed, which is what makes revocation real: signing out invalidates the token everywhere instead of waiting for it to expire. The cost is that the token store is now on the critical path for sign-in.
- Create AccountPOST
/api/auth/register - LoginPOST
/api/auth/login - GooglePOST
/api/auth/googlefederated identity
- Refresh SessionPOST
/api/auth/refreshrotates, revocable
- LogoutPOST
/api/auth/logout
Data model
Seventeen models. The interesting ones are where the record structure meets the identity structure.
Prescriptionembedded medicine listThe medicine list is variable-length and always read with its parent, so it is embedded. There is no read path that wants a medicine without its prescription.
MedicalRecordheterogeneous, sparsely populatedVitals, lab results, imaging, and attachments differ from visit to visit. This is the collection that justified a document store over a relational schema: the alternative is a wide table mostly full of nulls, or a migration every time a new result type appears.
Patient and FamilyMemberclinical profile identifiersA patient account can hold records for people who do not have accounts. Family members are clinical profiles without credentials, which is why a second identifier space exists at all.
RevenueEntry and Analyticsdenormalised, written by a scheduled jobAnalytics are snapshots computed on a schedule rather than aggregated per request. It keeps dashboards fast, and it is the reason a failed write sequence can leave the ledger and the counters disagreeing.
Conversation and Messagereferenced, splitSplit so a long thread does not grow one document without bound. Message bodies are encrypted with a dedicated key. See the challenge below for what happens when that key is not configured.
ConnectionRequestexplicit relationshipA doctor cannot read a patient's history because they share a clinic. The relationship is a record that has to exist, which makes access auditable rather than implied.
Challenges
The model returned things that were not JSON
Problem
Early prescription parsing came back with explanatory text before the JSON, Markdown code fences around it, or a structure that stopped mid-object.
Every one of those is a parse failure, and the tempting fix, extracting whatever parsed and saving the rest, is the dangerous one. A prescription form with four of five fields populated looks complete.
How it was solved
Enforced JSON output, a controlled sampling temperature, and server-side validation of the parsed result before anything is written.
Anything invalid falls back to manual entry rather than being saved as an incomplete prescription. The doctor types it instead, which is slower and correct.
The token store went down and took sign-in with it
Problem
During testing the external token store became unreachable. Sign-in failed outright, because refresh tokens could not be written.
The application handles the store being unconfigured: it falls back. It did not handle the store being configured and then unavailable, which is a different state and the more likely one in production.
How it was solved
The immediate cause was understood and the failure is documented rather than papered over: server-side revocation is worth having, and the price is that the store sits on the authentication critical path.
I have not fixed this. The correct answer is a circuit breaker with a degraded mode that issues shorter-lived tokens when the store is unreachable, and it is not built.
Urdu is not English laid out backwards
Problem
Switching to Urdu produced a layout that was mirrored but wrong: cramped line heights, clipped descenders, and spacing that read as broken to anyone who actually reads Urdu.
Nastaliq typography has different vertical characteristics from Latin type. A right-to-left flip handles direction and nothing else, and I had assumed direction was the whole problem.
How it was solved
An Urdu-specific typography scale and direction-aware spacing throughout, rather than a single global mirror. Line height, letter spacing, and vertical rhythm are set per script.
Message encryption falls back to the wrong key
Problem
Message bodies are encrypted with a dedicated key. When that key is absent from the environment, the system derives one from the token signing secret instead.
It means a single leaked secret compromises both authentication and message confidentiality. Two security domains that should fail independently are coupled by a convenience fallback, and the example environment file does not list the dedicated key, so the fallback is the default path, not the exception.
How it was solved
It is documented as a known weakness rather than closed, and I am listing it here for the same reason. The fix is to refuse to start without an explicit key, which is a better failure than starting insecurely.
Practices
- Patient audio never leaves the browser. the strongest privacy property in the system, and it came from a budget constraint rather than from foresight.
- Server-side refresh-token revocation. signing out actually invalidates, rather than waiting for expiry.
- Explicit doctor–patient relationships. access requires a record, so it can be audited.
- AI output validated before persistence. invalid results are rejected, never partially saved.
- Scheduled analytics. dashboards read snapshots instead of aggregating live.
- No credentials in version control. environment files excluded, and the report documenting this system reproduces no values.
Named plainly, because a practices list that only lists successes is marketing: there is no rate limiting and there are no security headers. Express provides neither by default and neither was added. On a system holding clinical data that is the most serious omission on this page.
Metrics
- 17
- Mongoose models
- 96
- Application routes
- 06
- Team size
- 05
- Duration (months)
counted
counted
counted
counted
Lessons
Getting the structure right mattered more than getting the transcription perfect. Urdu recognition is imperfect and will stay imperfect, but a doctor correcting two words in a correctly-shaped prescription is doing something very different from a doctor checking whether a form silently dropped a field. Designing the failure case first was the best decision in the project.
Choosing a component because it works in the deployment target changes the deployment target. The token store was chosen for serverless reachability, and it became a hard dependency of authentication. Socket.IO was chosen for the right abstraction, and it made the serverless deployment partial. Both were reasonable individually and neither was evaluated against the other.
A framework that supplies nothing by default supplies nothing by default. I chose Express knowing it was minimal, then never went back for the headers and the rate limiting that "minimal" was supposed to mean I would add myself. The gap is not an oversight in configuration. It is what happens when the cost of a choice is accepted in principle and never paid.
Building something bilingual taught me that internationalisation is a typography problem wearing a translation problem's clothes. The strings were the easy half.
Links
Related
Related work
The LearnX
- education
- video
- payments
- caching
Instructors selling premium video courses need their content protected from copying, payments handled reliably, and students enrolled automatically without manual admin.
The Smart Cart
- e-commerce
- real-time
- payments
- databases
Small sellers need a storefront they control without building one, and buyers need one place to shop across sellers with secure payment and direct contact with the seller.
Open to full-time remote roles and freelance work.