Problem
Most rideshare platforms in southern Africa are forks of products designed for a single hard-currency market. They assume one currency, one payment rail and one regulatory regime. Vaye had to ship into two markets at once — Zimbabwe (ZiG) and South Africa (ZAR) — with different payment providers, different phone-number formats, two distinct data-protection regimes (Zimbabwe DPA + POPIA), and operators who needed to run the whole thing from an office on an intranet rather than a cloud SaaS dashboard.
Approach
I built the platform as four discrete apps against one backend, sharing a typed contract:
- Rider app (
VayeExpoFrontFull) — Expo SDK 54 / React Native 0.81 / TypeScript. Reanimated worklets for animated trip cards,expo-secure-storefor tokens,useReducer+ Context for trip and auth state, battery-aware location tracking that throttles when stationary and ramps up during active rides. - Driver app (
vaye-drive-buddy) — Vite + React + Capacitor 7. Background geolocation through the native plugin instead of web polling, offline action queue for ride accept/reject, large-target request modal with haptics + sound for incoming jobs. - Admin ops centre (
mindful-prompt-maker-main) — Vite + TanStack Router + shadcn/ui. Built specifically to be hosted on internal IIS, intranet-only, with strict CSP, IP allow-list capability and a deploy script that refuses to ship a build pointed at localhost. - Backend (
VayeBackend) — Express 5, Mongoose, Socket.IO, helmet, JWT, env-driven CORS allow-list, per-route rate limits, lean reads with compound indexes.
Multi-market support is enforced at the data layer: every monetary record stores a currency code alongside the amount, fare configuration and surge pricing are per-market, phone validation supports +263 and +27, and copy is locale-formatted. There is no place in the codebase where "ZAR" or "ZiG" is hardcoded as a default.
The admin centre was hardened for an internal-network deployment: a custom production web.config with HSTS, CSP, X-Frame-Options DENY, COOP/CORP, immutable asset cache, no-cache index.html and request filtering to block .env/.git/.map. A PowerShell deploy script validates env, builds, and mirrors dist/ to a UNC share via robocopy /MIR.
Outcome
- Four apps shipping against one consistent typed API.
- Real-time ride and delivery tracking with reconnect on flaky LTE.
- Production security baseline: OWASP Top 10 audited, zero hardcoded secrets, env-driven CORS allow-list, JWT with separate admin signing key.
- Admin dashboard goes from
git pullto live IIS site in a single PowerShell command, with a sub-30-second rollback path. - Multi-currency, multi-locale architecture that didn't bolt on later — it was the first design decision.




