All work
Software20252025 — present

BloodAfya

A live platform that finds a compatible blood donor nearby — and reaches them by push, SMS and email the moment blood is needed.

bloodafya.madaraka.work
LivePublic and in productionbloodafya.madaraka.work
3Alert channels per requestPush, SMS and email, sent together
8Blood types matched by compatibilityThe full ABO/Rh donor-compatibility table
26Automated testsUnit tests on matching and distance, end-to-end tests on the donor and request flows

The problem

When someone needs blood urgently, the search for a donor still runs on phone calls, social media appeals and relatives. People who would gladly give have no way of knowing that someone nearby needs their exact blood type, and the people looking have no fast way to find the donors who could help — so the time that matters most goes on searching.

Constraints

A match has to be medically right before it is fast: a donor is only offered when their blood is actually compatible, ABO and Rh, not merely the same letter.

An alert that fails to send must never stop a request from going out. One broken SMS gateway cannot take the other channels down with it.

Donors are on their phones and away from the site, so they have to be reachable without the app being open.

The credentials for SMS, email and push are keys to reach real people, so they could not sit in plain configuration.

Approach

Rank donors the way a blood bank would

Every candidate is scored on the two things that decide a match: compatibility, where an exact blood type ranks above a compatible one, and distance, measured with the Haversine formula inside a 20 km radius that widens to 50 km when it has to. Urgency lifts the whole score — 1.2× for high, 1.5× for an emergency — and a donor who can travel gets a bonus. The top twenty come back ranked. The scoring is a pure function with its own unit tests, because this is the part that must never be quietly wrong.

One alert, three channels, none of them a blocker

Every notification goes through a single orchestration point. When a request goes out it fans out across Web Push, SMS and email in parallel, each rendered from a template an admin can edit without a deploy. Each channel succeeds or fails on its own and a failure is logged rather than thrown, so a broken gateway weakens the alert instead of blocking the match.

Blood stock that follows the donations

Hospitals track stock lot by lot, by blood type and expiry date, scoped so each hospital sees only its own. Completing a match draws that blood type down and checks what is left against a low-stock threshold, and a hospital running low is alerted automatically — the same moment the requester hears their request was fulfilled and the donor earns their badge.

Analytics that count the right thing

One request notifies many donors, so measuring fulfilment per notification would make a working system look like it was failing. The admin analytics count it per request instead — did any of its matches complete — alongside response times, donation trends, stock levels by hospital and donor demographics.

Secrets encrypted, roles checked on the server

SMS, email and push credentials are managed from an admin screen and stored in PostgreSQL under AES-256-GCM, never as plaintext environment variables. Donor, hospital and admin roles are looked up on the server for every protected action; a role sent from the browser is never trusted.

Architecture

A Next.js application over PostgreSQL. A request is scored against compatible donors nearby and fanned out across three alert channels at once; hospitals and admins read the same records back as stock and analytics.

Outcome

BloodAfya is live at bloodafya.madaraka.work. A request goes out, compatible donors nearby are ranked and alerted across push, SMS and email, and the match is followed through to a completed donation — with the hospital’s stock drawn down and the donor’s badges awarded at the end of it.

Loading Lincoln Madaraka