A unified, real-time platform that transforms the college dispensary from paper trails into a connected digital practice — for students, doctors, and administrators.
Live Demo · Documentation · Report a Bug · Request a Feature
Click to expand
DormDoc is a full-stack, production-grade web application engineered to digitise every workflow inside a campus medical centre. From the moment a student scans a QR code at the counter to the moment an administrator audits monthly inventory, the entire patient journey lives inside a single, secure, real-time platform.
The system replaces fragmented paper records, manual queues, and siloed spreadsheets with a unified React + Express + Supabase platform — purpose-built for the scale, reliability, and access-control requirements of an institutional healthcare environment.
"A campus clinic should run with the same precision as the hospitals its students may one day work in."
| Pain Point (Traditional Clinic) | DormDoc Solution |
|---|---|
| Paper prescriptions get lost | Digital prescriptions signed & retrievable anytime |
| Long queues at the dispensary | QR-code check-in + slot booking |
| No visibility into emergencies | One-tap SOS with live GPS dispatch |
| Inventory stockouts | Threshold-based alerts & auto-reorder reports |
| No data for decision-making | Analytics dashboard with trend visualisation |
| Manual leave verification | Linked prescriptions auto-validate leave requests |
| Disconnected ambulance dispatch | Live fleet tracking & queue management |
|
|
|
|
| Layer | Technologies |
|---|---|
| Frontend | React 18 · Material-UI · React Query · React Router · Recharts · @supabase/supabase-js |
| Backend | Node.js (≥18) · Express · @supabase/supabase-js (service-role) · jsonwebtoken (Supabase JWT verify) |
| Database | Supabase Postgres (15+) with Row-Level Security |
| Auth | Supabase Auth — email OTP, JWT (HS256) |
| Realtime | Supabase Realtime postgres_changes over Websockets |
| Storage | Supabase Storage (private prescriptions bucket, signed URLs) |
| Security | Helmet · CORS · express-rate-limit · express-validator |
| Integrations | Nodemailer (SMTP) · Groq / OpenAI / Cohere (AI chat) · QRCode |
| Tooling | Supabase CLI · ESLint · Husky · lint-staged · Nodemon · Concurrently |
| CI | GitHub Actions |
See
MIGRATION.mdfor the full record of how this stack replaced the original MongoDB / Clerk / Socket.io / Multer one across PRs #12–26.
graph TD
subgraph Client["🖥️ React Client — src/client"]
UI[Material-UI Components]
RQ[React Query Cache]
CTX[Auth & Realtime Contexts]
SBC[supabase-js client]
end
subgraph Server["⚙️ Express API — src/server"]
MW[Helmet · CORS · Rate-limit · Supabase JWT verify]
RT[REST Routes — student / doctor / admin / hod]
SVC[Service Layer — hodService, analytics services]
SBA[supabase-js service-role + per-request scoped client]
end
subgraph Supabase["🟢 Supabase project"]
DB[(Postgres + RLS)]
AUTH[Auth — email OTP]
RT2[Realtime — postgres_changes]
STOR[Storage — prescriptions bucket]
end
subgraph External["🌐 External Services"]
AI[AI — Groq / OpenAI / Cohere]
MAIL[SMTP — Nodemailer]
QR[QR-Code Generator]
end
UI -->|HTTPS / Axios| MW
SBC -->|Auth + Realtime + Storage| AUTH
SBC <-->|postgres_changes| RT2
SBC -->|signed URL| STOR
CTX --> UI
RQ --> UI
MW --> RT
RT --> SVC
SVC --> SBA
SBA -->|PostgREST| DB
SBA -->|admin API| AUTH
SBA -->|upload / delete| STOR
SVC --> AI
SVC --> MAIL
SVC --> QR
style Client fill:#dbeafe,stroke:#3b82f6,color:#1e3a8a
style Server fill:#dcfce7,stroke:#10b981,color:#064e3b
style Supabase fill:#d1fae5,stroke:#059669,color:#064e3b
style External fill:#fef3c7,stroke:#f59e0b,color:#78350f
- Client issues an authenticated request bearing a Supabase JWT.
- Middleware stack applies Helmet, CORS, rate-limiting, and HS256 JWT verification against
SUPABASE_JWT_SECRET; loads the caller's profile + role row and attaches areq.sbSupabase client (user-scoped for real users, service-role for dev tokens). - Route handler delegates to a controller / service, which validates inputs.
- Service layer issues Supabase queries against Postgres, Storage, or the Auth admin API.
- RLS in Postgres enforces row-level access on every read/write.
- Live updates reach the client directly via the Supabase Realtime channel (no server roundtrip needed); RLS scopes which clients see which events.
DormDoc/
├── assets/ # Static assets (logo, branding)
├── docs/ # Extended documentation
├── scripts/ # Utility scripts (incl. mongo-to-supabase ETL)
├── supabase/ # Supabase project config
│ ├── config.toml
│ ├── migrations/ # SQL migrations (extensions, schema, RLS, storage, realtime)
│ └── tests/ # pgTAP RLS test suite
├── src/
│ ├── client/ # React frontend
│ │ └── src/
│ │ ├── components/
│ │ ├── contexts/ # AuthContext, RealtimeContext, DevBypassContext
│ │ ├── lib/ # supabase client export
│ │ ├── pages/
│ │ └── services/
│ └── server/ # Express backend
│ ├── controllers/
│ ├── db/ # supabase.js + storage.js helpers
│ ├── middleware/ # authenticateToken, requireRole, scopeToDepartment
│ ├── routes/ # one file per resource
│ ├── services/ # hodService, analytics services
│ └── server.js
├── .env.example
└── package.json
No
src/server/models/— Mongoose was removed at the end of Phase 3 (PR #23). The schema is the Postgres tables, defined insupabase/migrations/.
| Dependency | Minimum | Notes |
|---|---|---|
| Node.js | 18.0 | LTS recommended |
| npm | 9.0 | Bundled with Node.js |
| Supabase project | — | Free tier is enough. Note the project ref, URL, anon key, service-role key, and JWT secret. |
| Git | 2.30 | — |
# 1. Clone the repository
git clone https://github.com/mightbeanshuu/DormDoc.git
cd DormDoc
# 2. Install root + client dependencies
npm install
npm run install-client
# 3. Create your environment files
cp .env.example .env
# Then create .env.local (gitignored) with the secrets:
# SUPABASE_URL=https://<ref>.supabase.co
# SUPABASE_SERVICE_ROLE_KEY=...
# SUPABASE_JWT_SECRET=... # from Project Settings → API → JWT
# SUPABASE_ACCESS_TOKEN=... # personal access token, for supabase CLI
# And src/client/.env.development.local with:
# REACT_APP_SUPABASE_URL=https://<ref>.supabase.co
# REACT_APP_SUPABASE_ANON_KEY=...
# 4. Push the schema + RLS policies + Storage buckets + Realtime publication
npx supabase link --project-ref <your-ref>
npx supabase db push
# 5. Launch the full stack in dev mode
npm run devThe dev server boots:
- ⚛️ React client → http://localhost:3000
- 🔌 Express API → http://localhost:5000
In NODE_ENV=development the server accepts three bypass tokens (dev_token for student, hod_dev_token for HOD, admin_dev_token for admin) that skip Supabase Auth. Backed by real seeded auth.users rows so policy-respecting queries still work — see supabase/migrations/ and the memory notes for the seed SQL.
curl http://localhost:5000/api/health{
"status": "OK",
"timestamp": "2026-05-21T00:00:00.000Z",
"uptime": 123.456
}curl -X POST http://localhost:5000/api/student/book-appointment \
-H "Authorization: Bearer dev_token" \
-H "Content-Type: application/json" \
-d '{
"doctorId": "00000000-0000-0000-0000-000000000003",
"appointmentDate": "2026-05-25",
"appointmentTime": "10:00",
"symptoms": "Routine check-up"
}'{
"message": "Appointment booked successfully",
"appointment": {
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"status": "scheduled",
"appointment_date": "2026-05-25"
}
}curl -X POST http://localhost:5000/api/student/sos \
-H "Authorization: Bearer dev_token" \
-H "Content-Type: application/json" \
-d '{ "symptoms": "Severe chest pain", "location": { "address": "Hostel 3" } }'Runtime configuration is split across two files. .env holds committed defaults; .env.local holds secrets and overrides (gitignored).
| Variable | Required | Default | Purpose |
|---|---|---|---|
NODE_ENV |
development |
Runtime environment | |
PORT |
5000 |
Express server port | |
SUPABASE_URL |
✅ | — | https://<ref>.supabase.co |
SUPABASE_SERVICE_ROLE_KEY |
✅ | — | Service-role key (bypasses RLS — server only) |
SUPABASE_JWT_SECRET |
✅ | — | HS256 secret used to verify incoming JWTs |
SUPABASE_ACCESS_TOKEN |
— | Personal access token, for supabase CLI from non-TTY shells |
|
CLIENT_URL |
http://localhost:3000 |
Comma-separated allow-list of CORS origins | |
GROQ_API_KEY |
— | Groq API key (used by routes/chat.js) |
|
EMAIL_HOST / EMAIL_PORT / EMAIL_USER / EMAIL_PASS |
— | SMTP for leave-request notifications | |
MONGO_URI |
— | Only used by scripts/mongo-to-supabase-etl.js during cutover |
| Variable | Required | Purpose |
|---|---|---|
REACT_APP_SUPABASE_URL |
✅ | Same as server SUPABASE_URL |
REACT_APP_SUPABASE_ANON_KEY |
✅ | Anon key (RLS-respecting) |
REACT_APP_SERVER_URL |
Override the API base URL (default http://localhost:5001) |
⚠️ Never commit.env.localor.env.development.local. Both are git-ignored.
# Run the full test suite
npm test
# Lint the entire codebase
npm run lint
# Format with Prettier (if configured)
npm run formatTest coverage reports are generated under coverage/ and uploaded by CI on every push.
The Supabase migration is code-complete (see MIGRATION.md). Deployment artifacts:
- Database / Auth / Storage / Realtime: managed Supabase project (free tier targets 5K users). Schema lives in
supabase/migrations/—supabase db pushis idempotent. - Application: Node Express server + CRA static bundle. Intended target is Railway; the deploy runbook lands in a future PR alongside the cutover.
- Data cutover from a previous Mongo instance (if applicable): run
node scripts/mongo-to-supabase-etl.js --dry-runfirst, populateUSER_ID_MAPwith the Mongo → Supabase auth-id mapping, then a real run during the maintenance window.
For a local production build:
npm run build && npm start- Core React + Express scaffolding & role-based access
- Appointment booking, prescriptions, ambulance dispatch, SOS
- Analytics dashboard & inventory module
- AI chatbot integration (Groq tool-calling)
- Supabase migration — Postgres + Auth + Realtime + Storage (Phases 0–5, 8-ETL)
- Railway deploy + cutover runbook (Phase 7 + 8.2–8.4)
- Edge Function features: appointment reminders, MSG91 SMS, analytics aggregation (Phase 6)
- pgTAP RLS coverage expansion + load tests (Phase 9)
- Custom SMTP (Resend / Postmark / SES) — default Supabase only emails dashboard members
- Telemedicine video consultations (WebRTC)
- React Native mobile applications
See the open issues for a live list.
Contributions are what make open source thrive — every bug fix, feature, doc improvement, or suggestion is welcomed and appreciated.
- Fork the project
- Create your feature branch (
git checkout -b feat/amazing-feature) - Commit your changes (
git commit -m 'feat: add amazing feature') - Push to your branch (
git push origin feat/amazing-feature) - Open a Pull Request
Please review the Contributing Guide and Code of Conduct before opening a PR.
If you discover a security vulnerability, please do not open a public issue. Instead, follow the disclosure process outlined in SECURITY.md. Reports are triaged within 48 hours.
Distributed under the MIT License. See LICENSE for full text.
Copyright (c) 2026 DormDoc Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction...
Standing on the shoulders of giants — sincere thanks to the maintainers of:
React · Express · Supabase · PostgreSQL · Material-UI · Recharts · Helmet · Groq
And to every contributor, tester, and end-user whose feedback shaped this platform.