Doctor Appointment System
Full-stack healthcare platform where patients book appointments and doctors manage schedules, with role-based auth and real-time updates.
- Role
- Full stack — MERN
- Year
- 2024
- Stack
- MongoDB · Express · React · Node.js · JWT
- Links
- GitHub ↗

01
Overview
A three-role MERN application (patient, doctor, admin) that handles the full appointment lifecycle: discovery, booking, confirmation, rescheduling, and history. Built to explore realistic role-based access control patterns and clean separation between the API and the SPA.
02
Problem statement
Small clinics rely on WhatsApp and phone calls to manage bookings, leading to double-booking, missed appointments, and no audit trail. The goal was a lightweight web app that any clinic can self-host without paying for a heavyweight SaaS.
03
Architecture
- 01Backend: Express REST API with modular route/controller/service layers and Mongoose schemas for User, Doctor, Appointment.
- 02Auth: JWT access tokens with bcrypt-hashed passwords; middleware enforces role checks on every protected route.
- 03Frontend: React SPA with protected routes; per-role dashboards for patient, doctor, and admin.
- 04Data model: appointments reference doctor and patient by ObjectId with compound indexes on (doctorId, slot) to prevent double-booking at the database layer.
04
Tech stack
- MongoDB
- Express
- React
- Node.js
- JWT
05
Features
- Role-based dashboards for patients, doctors, and admins
- Slot-based booking with server-side conflict detection
- JWT-authenticated REST API with per-route role guards
- Admin approval workflow for new doctor registrations
06
Challenges
- Preventing double-booking under concurrent requests — solved with unique compound indexes and idempotent booking endpoints.
- Keeping the three role UIs consistent without duplicating code — extracted a shared layout and hook set.
- Managing token refresh cleanly on the client without leaking auth state into every component.
07
Results
- Full booking flow working end-to-end across three roles
- Zero double-bookings under load testing with 50 concurrent clients
- Reusable auth + role-guard middleware later reused in other projects
08
Lessons learned
- Push consistency constraints down to the database whenever possible — the API layer is not a good place to guard uniqueness.
- A shared UI shell keeps multi-role apps sane; duplication grows fast otherwise.
- REST is still perfectly good for CRUD-shaped apps; GraphQL would have been overkill here.
09