Hospital Management System
Yibera
Yibera is a web-based hospital management system — a public marketing site plus three role-based portals (patients, staff, admins) behind a security-first authentication layer. It unifies patient intake, appointments, prescriptions, lab results, pharmacy inventory, and billing into one operational system.
- PHP 8
- Custom MVC
- MySQL / MariaDB
- Tailwind CSS
- Vanilla JS
- Apache

Hospitals juggle disconnected workflows — patient intake, appointment requests, staff records, pharmacy stock, lab results, and billing — often spread across paper, spreadsheets, and siloed tools. Patients have no single place to register, book, and follow their care, and staff and admins have no unified operational view.
A full HMS with three role-based portals behind a security-first auth layer. Patients self-register, book and manage appointments, and view prescriptions, lab results, and invoices. Staff (created by admins) sign in to a clinical/operational view, while admins manage patients, staff, and pharmacy inventory and see analytics. Booking is currently request-and-confirm — an admin confirms each appointment — not real-time slot selection.
Frontend
Server-rendered PHP views + Tailwind (compiled, purged, minified); progressive enhancement with vanilla JS, Chart.js, AOS, Swiper. No SPA.
Backend
PHP 8 custom MVC — no framework or Composer. Front-controller + router with thin models over mysqli using prepared statements.
Database
MySQL / MariaDB. Schema self-provisions on first request — idempotent CREATE TABLE IF NOT EXISTS plus additive column migrations.
Notifications
Dependency-free SMTP client (raw sockets, SSL/STARTTLS, AUTH LOGIN) for OTP/verification, with mail() + file-log fallback.
Infra
Apache on shared hosting; .htaccess for forced HTTPS, asset caching, gzip, and security headers; gitignored env-style config for secrets.
- 01
Register / Activate
Self-signup, or email-OTP activate/reset for patients booked by an admin.
- 02
Onboarding
Optional, skippable profile completion.
- 03
Sign In
Password (bcrypt cost 12) + optional email-OTP 2FA, protected by brute-force lockout.
- 04
Book
Choose department + preferred date/time — appointment is created as pending.
- 05
Confirm
Admin/staff move it to confirmed or completed; the patient sees the status.
- 06
Follow Care
View prescriptions, lab results, and invoices; pay invoices (simulated).
- patient — demographics, insurance, portal auth
- staff — provider profile, department, portal auth
- admin_users — admin / super-admin accounts
- appointment — patient, department, date/time, status
- prescription — EMR records per patient
- lab_report — EMR lab results per patient
- invoice — billing: amount, status, due/paid
- medication — pharmacy inventory
- login_attempts — brute-force throttle ledger
Tap any frame to open the lightbox — use arrow keys or swipe to navigate.
Multi-actor auth with isolated guards
Three identity types (admin / patient / staff) live in separate tables and session namespaces via three guard classes, so a valid patient session can't traverse into staff or admin areas. More code than one users table with RBAC — but strong blast-radius isolation.
Security as defense-in-depth
CSRF tokens on every state-changing form, brute-force lockout (5 tries → 15 min, scoped per identifier + IP), password policy with rehash-on-login, opt-in email-OTP 2FA, session-ID regeneration, idle/absolute timeouts, and HTTPS/HSTS edge hardening.
Schema migrate-on-boot
No shell/CLI on shared hosting, so Database::migrate() runs idempotently on the first request of a session to self-heal the schema on deploy. It isn't versioned — at scale I'd move to a real migration runner in CI/CD.
Dependency-free transactional email
A from-scratch SMTP client (raw sockets, SSL/STARTTLS, AUTH LOGIN) sends OTP/verification anywhere, falling back to mail() then a file log. Gaps: no retries/queue, no bounce handling, and OTP send is synchronous on the request path.
Honest data-model tension
Public booking still writes to patient.Status while the portal added an appointment table for multiple bookings — a real dual-source-of-truth smell (admin stats still read patient.Status). The fix is to move all scheduling onto appointment and keep patient as pure identity.
Where it breaks at scale
Single Apache box, file-based sessions, same-host MySQL, synchronous email. Scaling out means Redis/DB sessions, managed MySQL with read replicas for reporting, a queue for email, a CDN/object store for images, and versioned CI/CD migrations.
Yibera is a working full hospital management system — a public site plus patient, staff, and admin portals over a 9-table MySQL schema, with multi-actor authentication, defense-in-depth security, and self-provisioning migrations — built on zero-dependency PHP 8 so it deploys on plain shared hosting.
- 01
Real availability & slot engine
- 02
Provider discovery & search
- 03
Payment gateway (real billing)
- 04
Unified identity service with RBAC
- 05
Versioned CI/CD migrations
- 06
Email job queue + provider
- 07
Redis sessions & caching
- 08
Managed MySQL read replicas
- 09
CDN / object store + WebP images
- 10
Structured logging, metrics & alerts