All work
Software20252025 — present

BloodAfya

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

Test it yourself — sign in with a shared test login, no sign-up needed.

  • Donordonor@example.com
  • Recipientrecipient@example.com
  • Password1234

LivePublic and in productionbloodafya.madaraka.work
3Alert channelsPush and SMS when blood is needed, email for what follows
8Blood types matched by compatibilityThe full ABO/Rh donor-compatibility table
119Automated tests110 unit tests on matching, sessions, alerts and dashboards; 9 end-to-end browser runs

Live demo

Try it yourself.

Sign in to BloodAfya as a donor or a recipient, and follow the path under each.

Donor

Give blood: see who your type can help, offer to donate, and earn your badges.

Email
donor@example.com
Password
1234

What to try

  1. Your dashboard opens on your blood type, how many people who’ve asked for blood it could help, and the most urgent requests.
  2. Press I Want to Donate, type your town, set the Available from date to today, fill in Medical conditions and press Submit Donation Offer — you land on every open request, ready to filter by blood type and urgency.
  3. Press All badges to see your points, lives saved and the leaderboard.

Recipient

Need blood: ask for it, and let the matcher find compatible donors nearby.

Email
recipient@example.com
Password
1234

What to try

  1. Your dashboard opens on your blood type, the most urgent requests and the top donors.
  2. Press I Need Blood, type Nairobi as your location, pick an urgency, describe the situation under Medical Situation, choose a hospital and press Submit Request — the matcher ranks compatible donors within 20 km and tells you how many it matched.
  3. Open Find Donors at the foot of the page to browse everyone who has offered blood and where they are.

Two shared test logins on the live product, put back to a clean state every 20 minutes. What you post shows to the next visitor, and alerts sent from these logins reach only other test accounts, by push — never a real donor, and never an SMS or email.

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. 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.

Three channels, one way out, none of them a blocker

Every notification goes through a single orchestration point. When a request goes out, the best matches are alerted by Web Push and SMS in parallel, and everything after it — an acceptance, a fulfilled request, low stock, a new badge — follows by push and email. Each message is rendered from a template an admin can edit without a deploy, and each channel succeeds or fails on its own: 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. 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.

One home, a different job for each role

Donors, hospitals and admins sign in to the same page and find their own work on it. A donor sees their blood type, how many people who have asked for blood it could help, their impact so far and the most urgent requests; a hospital sees which blood types are running under five units, with its inventory and analytics a tap away; an admin gets the analytics, the message templates and the delivery settings.

Keys encrypted, sessions signed

SMS, email and push credentials are managed from an admin screen and stored in PostgreSQL under AES-256-GCM, never as plaintext environment variables, and that screen only ever shows them masked. Who is calling comes from a signed, httpOnly session cookie, and their role is looked up on the server for every protected action — a user id sent from the browser is never trusted.

A public demo that cannot reach a real person

Visitors get shared test logins on the live product. Any account on a reserved test domain is treated as a demo: an alert sent from one reaches only other test accounts, and only by push — never a real donor, never an SMS or an email. Photo uploads are switched off for them, and a database function puts every demo account back to a known starting state on a timer, so the next visitor finds the product as it should be.

Architecture

A Next.js application over PostgreSQL. A request is scored against compatible donors nearby and alerted by push and SMS 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 by push and SMS, 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