Preview
Visit unirides.unicorns.run to experience a production-grade ride-sharing app built from the ground up. Request rides between any two locations in Nairobi with real-time fare estimates, route visualization, and live driver tracking.
Architecture
Frontend — Next.js 16 PWA on Fly.io
The frontend is a fully client-rendered Progressive Web App built with Next.js 16, TailwindCSS v4, and the @vis.gl/react-google-maps SDK. It runs on Fly.io with scale-to-zero for $0 idle cost.
Google Maps Platform Integration (5 APIs)
- Maps JavaScript API — Satellite/hybrid map with Advanced Markers, custom Map ID, and repositioned controls for mobile UX
- Places API (Autocomplete) — Real-time location search for both pickup and dropoff with "Powered by Google" attribution
- Geocoding API — Reverse geocode GPS coordinates to human-readable addresses with retry logic
- Directions API — Route polyline rendering between pickup and dropoff via DirectionsService/DirectionsRenderer
- Distance Matrix API — Live ETA and remaining distance calculation with dynamic polling (3s during active ride, 10s when accepted)
State Management & Real-Time Updates
Zustand manages ride state including current location, pickup/dropoff, fare estimates, driver location, recent searches, and saved places. Real-time ride tracking uses WebSocket with automatic fallback to HTTP polling at status-aware intervals.
Kenyan Market-Rate Pricing
Fares are calculated client-side using post-2025 Kenyan ride-sharing rates (aligned with Bolt/Uber after the 50% fare increase mandated by Kenya's transport authority):
const KENYAN_RATES = {
base_fare: 120, // KES
per_km: 35, // KES — between Bolt (33) and Uber (36.8)
per_minute: 3.5, // KES
minimum_fare: 250, // KES
booking_fee: 20, // KES
}A 21km trip from Kiserian to Lavington Mall shows ~KES 1,000 — matching real-world Bolt/Uber estimates.
Mobile-First UX
- Satellite/hybrid map view with repositioned controls (zoom at right-center, fullscreen at left-top)
- Sticky top bar with theme toggle and login above mobile browser chrome (z-20 + safe-area-inset)
- Opaque ride panels (bg-black/95) for readability over satellite imagery
- Safe-area-inset support for iOS notch and Android gesture navigation
- Haptic feedback on ride events via the Vibration API
Backend — FastAPI on GCP Cloud Run
Production-grade Python backend with:
- FastAPI with async SQLAlchemy 2.0 and Pydantic v2 schemas
- Neon PostgreSQL (free tier) with Alembic migrations
- Upstash Redis for session management, rate limiting, and real-time pub/sub
- Google Maps server-side APIs for route calculation, fare estimation, and driver matching
- JWT authentication with bcrypt password hashing and token refresh
- WebSocket endpoint for real-time ride status updates
- Structured logging with correlation IDs via structlog
GCP Services Used
| Service | Purpose |
|---|---|
| Cloud Run | API hosting, scale-to-zero |
| Secret Manager | JWT secret, DB URL, API keys |
| Cloud Build | CI/CD pipeline |
| Artifact Registry | Docker image storage |
| Google Maps Platform | Directions, Distance Matrix, Geocoding, Places |
Authentication
NextAuth v5 with Google OAuth provider. Sessions are managed server-side with JWT tokens passed to the FastAPI backend. AUTH_TRUST_HOST=true for non-localhost deployments on Fly.io.
Technology
- Next.js 16 (Turbopack)
- TypeScript
- TailwindCSS v4
- @vis.gl/react-google-maps
- Google Maps Platform (5 APIs)
- Zustand (state management)
- NextAuth v5 (Google OAuth)
- FastAPI (Python)
- SQLAlchemy 2.0 (async)
- Neon PostgreSQL
- Upstash Redis
- GCP Cloud Run
- Fly.io (frontend)
- Docker (multi-stage builds)