A full-stack healthcare marketplace for the Philippines — patients find and book verified doctors, pay securely, chat in real time, and receive digital prescriptions.
Demo accounts are created by running
bun run seedfrom theserver/directory. Credentials are printed to the console after seeding completes.
- Auth — Register, login, email verification, password reset. JWT access token (15 min, memory-only) + refresh token (7 days, httpOnly cookie) with rotation and reuse detection.
- Doctor marketplace — Browse and filter doctors by specialization, fee, and rating. View profiles, schedules, and available slots.
- Appointments — Book slots, confirm, complete, or cancel. Double-booking prevention built in.
- Real-time chat — Socket.io chat room per confirmed appointment. Unlocked only for the patient and doctor in that appointment.
- Prescriptions — Doctors write digital prescriptions with medications. Patients view per-appointment and across all visits.
- Payments — PayMongo integration (GCash, Maya, card). App-level escrow: funds held on booking, released on completion, refunded on cancel.
- Reviews — Star ratings after completed appointments. Doctor average rating updates automatically.
- Admin panel — Verify doctors, manage users, view platform stats.
- Role dashboards — Personalized dashboards for patient, doctor, and admin with real-time data.
| Layer | Tools |
|---|---|
| Frontend | React 18, Vite, TypeScript, Tailwind v4, Radix UI + CVA, React Router v6, Zustand, TanStack Query, React Hook Form + Zod |
| Backend | Node.js, Express, TypeScript, Drizzle ORM, PostgreSQL 17, Socket.io |
| Auth | JWT (access + refresh), bcrypt, httpOnly cookies, rate limiting |
| Payments | PayMongo (GCash, Maya, cards) |
| Tooling | Bun, Vitest, Supertest, Playwright, Husky, commitlint, ESLint, Prettier |
| Deploy | Vercel (client) · Render (server) · Neon (Postgres) |
flowchart LR
subgraph Browser
C[React + Vite]
end
subgraph Server["Node + Express (Render)"]
A[REST API]
W[Socket.io]
A --- W
end
subgraph Data["Neon (Postgres 17)"]
P[(PostgreSQL)]
end
subgraph External
PM[PayMongo]
R[Resend]
end
C -- HTTPS + httpOnly cookie --> A
C -- WSS + JWT handshake --> W
A --> P
W --> P
A --> PM
A --> R
Auth: access token in Zustand (memory-only, lost on tab close by design). Refresh token is an httpOnly + secure cookie. On every page load the client calls /api/auth/refresh to restore the session silently. On a 401, an Axios interceptor refreshes via single-flight and retries the original request automatically.
See docs/architecture.md for sequence diagrams of the auth flow and payment escrow flow.
Prerequisites: Bun ≥ 1.1, Node ≥ 20.19, PostgreSQL 17 running locally.
# 1. Clone and install
git clone https://github.com/tatineeeeeee/hilom.git
cd hilom
bun install
# 2. Configure env
cp .env.example .env
# edit .env — set DATABASE_URL to your local Postgres
# 3. Migrate schema and seed
bun run --filter server db:migrate
bun run --filter server db:seed:all
# 4. Run both apps (client :5173, server :4000)
bun run devOptional — local SMTP catcher for email flows:
bunx maildev # web UI at http://localhost:1080Swagger UI at /api/docs — generated from the same Zod schemas used at runtime, so it never drifts from the actual API. Admin endpoints are filtered out of the public spec.
hilom/
├── client/ # React app (Vite)
│ └── src/
│ ├── app/ # router, providers
│ ├── components/ # shared UI, layout
│ ├── features/ # vertical slices (auth, appointments, chat, ...)
│ └── lib/ # api client, utils
├── server/ # Express API
│ └── src/
│ ├── config/ # env, db, logger
│ ├── controllers/
│ ├── db/ # Drizzle schema + migrations + seeds
│ ├── middleware/
│ ├── routes/
│ ├── schemas/ # Zod request schemas
│ └── services/
├── e2e/ # Playwright tests
├── docs/ # Architecture + sequence diagrams
└── phases.md # Full project roadmap