Crowdsourced, offline-first trotro route & fare optimizer for Ghana (FastAPI + Next.js PWA)
# TroTro Optimizer 🚐
A **crowdsourced, offline-first trotro (shared minibus) route & fare optimizer for Ghana.**
Find the best route between two points — which trotros to take, where to change, estimated
fare and time — built on community data and working fully offline.
---
## Features
- **Route engine** — Multi-leg trotro routing (station → station with transfers). Returns
*fastest / cheapest / fewest-changes* options, walking legs to/from stations, and fare per
leg + total. The network is modelled as a weighted graph (stations = nodes, route segments =
edges) and solved with a multi-criteria Dijkstra. The same algorithm runs on the server
(Python) and in the browser (TypeScript) so results are identical online and offline.
- **Crowdsourcing** — Users submit and correct routes, fares, and station locations. Fare
changes (fuel-price driven) propagate through community reports with **trust/verification
scoring** and a **moderation queue**. Contributions are auto-applied once they cross a
confidence threshold; otherwise a moderator reviews them.
- **Offline-first** — The full routing dataset is packaged and downloaded to the device
(IndexedDB). Routing works with **zero network**. When back online the client pulls deltas
(`/sync/changes?since=…`) and pushes queued contributions.
## Why Next.js PWA (not Expo)
| Concern | Next.js PWA | Expo / RN |
|---|---|---|
| Distribution in Ghana | Instant URL, "Add to Home Screen", no store | App-store friction, updates gated |
| Offline | Service Worker + IndexedDB (full parity) | AsyncSQLite (also good) |
| One codebase / deploy | Single repo, edge-deployable | Needs EAS build pipeline |
| Maps offline | MapLibre GL + local vector tiles | MapLibre RN |
For a data-first utility that must reach low-end Android phones with flaky data plans, an
installable PWA is the lowest-friction path to *true* offline. The architecture keeps the map
and routing engine framework-agnostic, so an Expo shell can be added later reusing the sam …