01Mobile · API · Operator portals·2025 — 2026
Coil
Fuel you pay for in the app and collect at the pump.
- Role
- React Native & full-stack engineer (contract)
- Years
- 2025 — 2026
- Stack
- React Native · Expo Router · TypeScript · Node.js
Screens
Coil · 05 frames
Wallet and nearby stations04 Find a station and check prices05
01Overview
Drivers see which nearby stations have fuel, fund a naira wallet, and pay with a QR code. The ledger moves only when an attendant scans it. No card on the terminal.
02The problem
You cannot tell which station has fuel, or today's price, without driving there.
At the pump the POS hangs, and handing over a debit card is a fraud risk. If the app debits a wallet and the pump never dispenses, the customer has lost money.
03What we built
Stations are GeoJSON. A 2dsphere query returns live price and stock inside 5 km.
A purchase is a QR, not a completed debit. The attendant scans it — camera or NexGo POS — and only then does the ledger move.
04My role
Expo app, Express API, Paystack webhooks, and the operator portals.
- Expo app: wallet, Paystack, PIN, biometrics, QR receipts
- Station search within 5 km (GPS, maps, MongoDB 2dsphere)
- Ledger writes in a transaction; Paystack credits verified by HMAC and idempotent
- Admin, HQ, branch, and business portals on the same API
05Request path
01
Expo app
Driver
02
REST API
Express + JWT
03
Ledger
Mongo txns
04
Paystack
HMAC webhook
05
Attendant
QR / POS scan
A purchase stays pending until the attendant scans. Paystack retries webhooks, so every credit has to be idempotent.
06Technical decisions
- 01
Pending until the scan
Purchases stay PENDING_SCAN until the QR completes, so a missed scan never leaves the books.
- 02
Idempotent webhook credits
Credits are keyed on the Paystack reference and written in a MongoDB transaction after the HMAC check.
- 03
Rate limits on money routes
Top-up, purchase, and attendant scan have their own limits. Volume is the cheap attack.
- 04
Search in the database
Proximity, price, and stock come from a 2dsphere index, not a filter in application code.
07Stack
- React Native
- Expo Router
- TypeScript
- Node.js
- Express
- MongoDB
- Paystack
- NexGo POS
- React 19
- Vite
- Leaflet
08Verification
- coil.africa
The live product.
Public
- Coil Africa on the App Store
The Expo app I work on, shipped to the App Store.
Public
- 1M+ users — Coil's own figure
Published on Coil's site.
Public
Want the code open?
I'll walk through the repos and what I'd rebuild.