Priestly
← All projects

Case study 02 / 03 · Health / Location-based web app

PharMap

An app that helps people in Cameroon find a medicine: which nearby pharmacies have it in stock, at what price, and how fresh that information is. Pharmacies manage their own listings, and an admin verifies them.

Role
Solo · frontend + backend
Status
MVP live · private code
Stack
React · NestJS · PostgreSQL
Updated
Oct 2026
Live demo Private code, available on request
pharmap-web.vercel.app
PharMap homepage: “Find your medicine before you leave home”, a medicine search box, and a live card showing which verified pharmacies have Paracetamol, with prices and stock levels

01

What the client needed, and what I built

When someone in Cameroon needs a medicine, they usually go from pharmacy to pharmacy or phone around. Stock information, where it exists at all, is often out of date, and there's no easy way to know which pharmacy to trust.

01 · Find

ProblemTo find a medicine, people go from pharmacy to pharmacy or phone around.

BuiltSearch by generic name or local brand name (Doliprane, Panadol). The nearest pharmacy that has it, with stock updated in the last 14 days, comes first.

Plain PostgreSQL search: every word matched against name, generic and brand names, accents ignored, ranked by matches

Where Paracetamol is in stock: the best option near you, Pharmacie Kotto, in stock at 1,500 FCFA 0.4 km away, with Call and Directions buttons, then other pharmacies with their prices and stock

02 · Trust

ProblemStock information is often out of date, and there's no easy way to know which pharmacy to trust.

BuiltEach pharmacy shows the price, the stock status and how recently it was updated. Only pharmacies checked by an admin are marked verified.

Verification is a state machine, and every status change is recorded in an audit trail

Pharmacie de la Cité Bonamoussadi in Douala: open now, verified, rated 4.0, Call and Directions buttons, a searchable list of its medicines with prices and when each was reported, and its opening hours

03 · Back in stock

ProblemWhen a medicine is out of stock, patients have to keep checking.

BuiltWhen a pharmacy marks it back in stock, the patients waiting for it are notified.

Notifications are written in the same database transaction as the stock change, so no one is missed

Inventory of Pharmacie du Carrefour Warda: filters for needs update, out and low, and In stock, Low and Out buttons with the price on each medicine
All features (15)
  • Search medicines by name, generic name or local brand name (e.g. Doliprane or Panadol for paracetamol)
  • See which pharmacies have a medicine, with the price in FCFA, the stock status and how fresh the data is ("Reported 2 hours ago", flagged after 14 days)
  • Pharmacies near me on a map (Leaflet + OpenStreetMap), with opening hours and "open now" on each pharmacy
  • Pharmacy registration in 3 steps: find the pharmacy on OpenStreetMap or drop a pin, add the details, review. The browser's Back button works at every step
  • Pharmacies manage their own stock: status, quantity and price for each medicine
  • Admin verification with a real state machine (pending, under review, verified, rejected, suspended) and an audit trail of who decided what
  • “Best option near you”: the nearest pharmacy that has the medicine, with stock updated in the last 14 days, comes first, with Call and Directions buttons
  • A dashboard for pharmacy owners: several pharmacies on one account, what needs attention (stock not updated in 14 days, reports), and opening hours with lunch breaks
  • One admin queue for everything waiting on a decision, oldest first: new pharmacies, reviews in progress, reports and new medicines
  • Verification with a checklist (the pin is on a real pharmacy, the phone answers, the name matches its sign), and reports the admin can resolve, dismiss or turn into a suspension
  • Pharmacies can add a medicine the catalogue doesn't have; it's usable right away, and the admin approves it, fixes the name or merges a duplicate
  • Restock notifications: a patient can ask to be told when an out-of-stock medicine is back at a pharmacy
  • Ratings and reviews, and a way to report a wrong listing
  • English and French, installable on a phone like an app, with a mobile bottom navigation that adapts to the account type
  • Automated tests (unit and end-to-end) run on every push in CI

02

How it's built

I built PharMap as an installable web app (PWA) with a React frontend and a NestJS API. Patients search for a medicine and see which verified pharmacies have it, with the price and how recently the stock was updated. Pharmacies register themselves on a map and keep their inventory up to date. An admin verifies each pharmacy before it's shown as verified. It works in English and French.

Frontend
React + TypeScript + Vite + TailwindA fast, installable PWA. It's an app people log into, so it doesn't need server rendering.
Maps
Leaflet + OpenStreetMapFree, with no billing account or API key, and good place search for Cameroon.
Backend
NestJS + TypeScriptOne module per area (auth, medicines, pharmacies, reviews, notifications), with role checks enforced on the server.
Database
PostgreSQL (Neon) + PrismaPharmacies, stock, members and reviews are all linked, and stock updates need transactions.
Hosting
Vercel + Render (Docker)The web app on Vercel, the API on Render from its own Dockerfile. Free tiers that fit this app without losing features.

03

What was hard

  • Search had to change to go live. It started on Meilisearch, but free hosting wipes the disk on restart, which deletes its index. I moved search into Postgres, trading typo tolerance for something that runs on the database we already have.
  • Keeping notifications exact. When a pharmacy marks a medicine back in stock, waiting patients are notified in the same database transaction, so there's never a moment where stock says "in stock" and a subscriber was missed.
  • Cold starts on free hosting. The database sleeps after 5 minutes and the API after 15, so deployments failed while the database woke up. A longer connection timeout fixed the deploys, and a scheduled ping keeps the API awake.
  • One account, several roles. A person can be a patient and a pharmacy owner at the same time, so roles are worked out from their data instead of being stored as a single value.

04

Result

It's live as an MVP: the web app on Vercel, the API on Render and the database on Neon, with unit and end-to-end tests running on every push. The code is in a private repository.

05

Screens

9 screens · tap to enlarge

Need an app like this?

Search, maps and verified listings, in English and French.

Talk on WhatsApp