Inspiration
In Nigeria, a paper prescription is only the start of the work. Patients have to decode handwriting, walk between pharmacies to find who has the medicine in stock and at what price, and then remember on their own how many pills to take and when. Pharmacists have the mirror-image problem: stock books are on paper, and nobody knows which lines will run out today.
We also read the Nigerian research on this. Reminder apps exist but are narrow, mostly single-disease (HIV, glaucoma). Inventory systems exist but only at facility level. No Nigerian-reviewed system closes the loop from pill count at home → consumption → refill alert → reorder.
We wanted to close that loop, from a paper prescription to a taken dose.
What it does
Prescilly is a mobile-first web app for prescription-based pharmacy commerce in Nigeria.
- Scan. Photograph a paper prescription, or pick one from the gallery. The camera has torch control.
- Read. AI (Google Gemini) turns the slip into structured records: name, dosage, frequency, duration, route, instructions and a confidence score per medicine. A read-aloud option speaks the result.
- Match. The app checks live pharmacy inventories for price, stock and logistics fee. A single order can split across two pharmacies.
- Pay. Checkout takes a delivery address and a simulated Stripe or Paystack payment. This is demo only, so no real money moves.
- Track. A rider moves along a live Leaflet map route to your door.
- Remember. Per-dose reminders run for the whole course. Mark doses taken, undo, snooze, and see 7-day adherence.
A pharmacy operator console (MedPlus / Alpha-Pharmacy) shows revenue, orders, staff on duty, riders available, a low-stock watchlist and a restock log. It also gives full inventory CRUD with stock adjustment, search, sort and undo-delete.
For judges, "Meet Ada" is a one-button demo. It seeds a four-medicine prescription that deliberately splits across two pharmacies, then walks through pharmacies, cart, checkout, payment and reminders.
How we built it
- Front end only. React 19, Vite, React Router and Leaflet, in plain JavaScript. The CSS is hand-written with design tokens and a three-layer cascade. There is no UI library, state library or CSS framework.
- No backend. The AI is a direct browser call to the Gemini REST API with the temperature set to 0. The "database" is a set of GitHub Gists holding the two pharmacy inventories, the patients and the orders. The demo runs with zero infrastructure.
- Quantity engine. We estimate how much to buy from the prescription text:
$$\text{tablets} = \text{doses per day} \times \text{days}$$
For liquids, with $v$ ml per dose, the volume is
$$\text{volume (ml)} = \lceil v \times \text{doses per day} \times \text{days} \rceil$$
- Cart logic. Lines are keyed by pharmacy and medicine. The logistics fee is charged once per supplier, so a split order is priced honestly.
- Delivery simulation. We use haversine distances and a sinusoidal bow on the route so the path looks like a road. A
requestAnimationFrameloop drives the 75-second run. - Reminder scheduling. Slots follow clinic conventions. "Before food" shifts the first dose 60 minutes earlier, and "bedtime" becomes a 22:00 dose.
- Design. We rebuilt the look and flow from a 31-frame reference reel and enforced it with a shared component library.
Challenges we ran into
- The UI must never wait on the network. Local work such as the cart and reminders is instant. Remote writes (stock decrement, order creation) run in the background under hard timeouts, and the UI moves on a timer.
- Concurrent writes with no database. A patient paying while a pharmacist restocks could overwrite each other. We re-read before every write. A same-pharmacy race on the patient side is still a known gap.
- Messy AI output. Models wrap JSON in code fences, add prose or return objects instead of arrays. We built a tolerant parser and a fallback to "one unit, confirm manually" when the duration is unclear.
- Pricing correctness. Counting tablets is not the same as selling packs. Pack-size-aware pricing is the biggest correctness gap we know of.
- Reminder end dates. Our first version used a naive regex for the course length, so "1 month" became a 1-day course. We identified it and the fix is queued.
- Secrets in a browser-only architecture. Vite inlines
VITE_*variables, so the Gemini key and gist token ship in the bundle. That is acceptable for a closed demo but not for production. - Polish under a deadline. This was a five-day hackathon. We had to balance visual fidelity, accessibility and a working end-to-end flow.
Accomplishments that we're proud of
- A complete loop in one app: scan, read, compare, split, pay, track, remind and measure adherence.
- A two-sided product: the patient app and the pharmacy operator console share live data.
- A one-tap demo path that shows the whole system working in under two minutes.
- A real multi-pharmacy cart with per-supplier fees.
- Accessibility basics: labelled inputs, aria-labels on icon-only buttons, text-to-speech and
prefers-reduced-motionsupport. - An honest, documented list of limitations, including security, clinical validation and pack size, rather than hiding them.
What we learned
- Design for failure first. Timeouts, fallbacks and optimistic UI matter more than the happy path when everything is over a flaky network.
- Structured output needs defensive parsing. Even with a strict prompt, treat model output as untrusted input.
- Zero-infrastructure demos are powerful and have a cost. Gists got us moving in minutes, but they come with rate limits, race conditions and exposed keys.
- Health tech needs humility. AI-derived quantities and schedules need a pharmacist in the loop before real use.
- A shared design system keeps speed and consistency. Reusing one component library kept the app coherent across more than a dozen screens.
What's next for Prescilly
- Patient-level restock loop. Track a pill count at home, decrement it as doses are marked taken, alert at a refill threshold, and offer one-tap reorder. This is the gap the literature review named.
- Real notifications. A service worker and Web Push, with the "30 minutes before, repeat hourly if ignored" pattern validated by Nigerian reminder systems.
- Pharmacist-in-the-loop. A verification queue where a pharmacist confirms the AI extraction before the cart is priced.
- Pack-size-aware pricing with a proper unit-of-measure catalogue.
- Serverless backend. One edge function to proxy Gemini and own the datastore token, plus authentication and per-patient scoping.
- More pharmacies. Replace the two hard-coded inventories with a queryable catalogue, geo-distance sorting and a true "cheapest pharmacy that has it" split engine.
- Better adherence scoring using a validated questionnaire model, and a printable prescription summary for clinic handover or family carers.
Built With
- css3
- gemini-api
- github-api
- github-gists
- google-gemini
- html5
- javascript
- leaflet.js
- localstorage
- material-design
- node.js
- npm
- openstreetmap
- oxlint
- react
- react-leaflet
- react-router
- responsive-design
- rest-api
- vite
- web-speech-api
Log in or sign up for Devpost to join the conversation.