Live natural-hazard map for Africa that plots events from NASA EONET and USGS, then finds the nearest hospitals and clinics from OpenStreetMap. Deployed across two web servers behind a HAProxy load balancer.
# East Africa Disaster Early-Warning Map
ALU Web Infrastructure summative — "Playing Around with APIs".
## Demo video
A short (~2 min) walkthrough showing the app running locally and through the load balancer:
**→
youtu.be
## Live deployment
**→
patient0.tech**
Served over HTTPS (Let's Encrypt) through a **HAProxy** load balancer (`Lb01`) doing
round-robin across two identical web nodes:
| Role | Host | Serves |
|---|---|---|
| Lb01 | HAProxy, `www.patient0.tech` | round-robin + TLS termination + HTTP→HTTPS redirect |
| Web01 | `7090-web-01` | nginx (static + `/api` reverse proxy) → Express on `:3000` |
| Web02 | `7090-web-02` | identical to Web01 |
| DB | Neon Postgres (`eu-central-1`) | users + saved settings, over TLS |
Round-robin is verifiable live — each response names the backend that served it:
```bash
for i in $(seq 10); do curl -s
patient0.tech; echo; done
# → alternates {"ok":true,"host":"7090-web-01"} / {"ok":true,"host":"7090-web-02"}
```
The load balancer uses an **application-level health check** (`option httpchk GET
/api/health`), so a node whose Express backend is down — even with nginx still up — is
pulled from rotation rather than returning 502s. The exact working LB config is committed
at `deploy/haproxy/haproxy.cfg`; full steps are in
`deploy/RUNBOOK.md`.
## The problem
Public hazard feeds (earthquakes, floods, storms) tell you *that* something is
happening, but not *what to do about it*. This app plots natural-hazard events across
Africa from **NASA EONET** and the **USGS earthquake feed**, and layers on the nearest
health facilities from **OpenStreetMap** (via the Overpass API), so a viewer near a
flagged event can answer "where do I go" in the same view, not by cross-referencing three
separate apps. It is explicitly not a weather app, joke generator, or converter — it
combines three independent live data sources into one decision-relevant view, with
filtering, sorting, and p …