A microservices-lite, cloud-native appointment booking platform for hospitals — built as the Software Architecture (SEN3244) project-based exam deliverable.
Patients can register, browse doctors by department, view real-time available slots (computed from each doctor's recurring availability, not manually maintained), book/cancel appointments, and doctors can confirm bookings. The platform is containerized, deployed to Kubernetes via a Jenkins CI/CD pipeline, provisioned with Terraform + Ansible, and observed with Prometheus/Grafana.
- Style: Layered monolith-per-service (API, Slot Engine, Data) packaged as independently
deployable frontend/backend containers — a pragmatic middle ground between a full microservices
split and a single monolith, justified in
docs/architecture_report.md. - Frontend: React (Vite) SPA, served by Nginx, reverse-proxies
/apito the backend. - Backend: Node.js/Express REST API, Sequelize ORM, JWT auth, Prometheus metrics.
- Database: PostgreSQL.
- Core innovation: the Slot Engine derives bookable time slots on the fly from a doctor's weekly availability minus existing bookings — no manual slot management required.
See docs/diagrams/ for component, deployment, infrastructure, and sequence diagrams.
backend/ Express REST API (controllers, models, routes, services, tests)
frontend/ React SPA (Vite)
k8s/ Kubernetes manifests (namespace, config, Postgres, backend, frontend, ingress, HPA)
ansible/ Playbooks: Docker install, app deployment
terraform/ VPS provisioning (DigitalOcean droplet + firewall)
jenkins/ Jenkinsfile (CI/CD pipeline) — also copied to repo root
monitoring/ Prometheus config, alert rules, Grafana dashboard JSON
docs/
api/openapi.yaml Swagger/OpenAPI 3.0 spec (served at /api-docs)
diagrams/ Architecture diagrams (component, deployment, infra, sequence)
scrum/ Product backlog, sprint backlogs, retrospectives, burndown charts
docker-compose.yml Full local stack: app + Postgres + Prometheus + Grafana + node-exporter
git clone <your-repo-url> && cd smart-hospital-booking
docker compose up --build| Service | URL |
|---|---|
| Frontend | http://localhost:8080 |
| Backend API | http://localhost:4000/api |
| API Docs (Swagger) | http://localhost:4000/api-docs |
| Prometheus | http://localhost:9090 |
| Grafana | http://localhost:3000 (admin / see docker-compose.yml) |
Seed demo data (after containers are up):
docker compose exec backend node src/config/seed.jsDemo accounts created: admin@hospital.com, amara.ngwa@hospital.com (doctor),
paul.tanyi@hospital.com (doctor), patient@hospital.com — all password <Role>@12345.
cd backend
npm install
npm test # runs Jest with coverage; threshold enforced at 80%kubectl apply -f k8s/00-namespace.yaml
kubectl apply -f k8s/01-configmap-secret.yaml
kubectl apply -f k8s/02-postgres.yaml
kubectl apply -f k8s/03-backend.yaml
kubectl apply -f k8s/04-frontend-ingress.yaml(Replace REGISTRY/... image placeholders in k8s/03-backend.yaml and k8s/04-frontend-ingress.yaml
with your pushed image tags — the Jenkins pipeline does this automatically.)
cd terraform
terraform init
terraform apply -var="do_token=$DO_TOKEN" -var="ssh_key_fingerprint=$SSH_FP"
cd ../ansible
ansible-playbook -i inventory.ini 01-install-docker.yml
ansible-playbook -i inventory.ini 02-deploy-app.ymlPush to main triggers the Jenkins pipeline (Jenkinsfile): install → lint → test (with
coverage) → build Docker images → push to registry → kubectl apply + rolling update on the
Kubernetes cluster.
Prometheus scrapes /metrics on the backend (request rate, p95 latency, appointments booked/
cancelled, error rate) and node-exporter (host CPU/memory). Grafana dashboard and alert rules
are pre-provisioned in monitoring/.
- Branch from
mainusingfeature/<short-description>. - Ensure
npm testpasses with ≥80% coverage before opening a PR. - Keep commits scoped and descriptive; the Jenkins pipeline blocks merges on failing tests.
MIT — academic project for SEN3244, Spring 2026.