React Native + Expo
Cross-platform app, New Architecture enabled. Expo Router for navigation, EAS for builds and over-the-air updates.
Technical details
Tsamaya is a React Native app backed by a geospatial database and a Python data pipeline with a Claude-assisted review step. Here’s how the pieces fit.
The stack
Cross-platform app, New Architecture enabled. Expo Router for navigation, EAS for builds and over-the-air updates.
Map tiles, Directions API for routing, and Geocoding for search and reverse-geocoding the map.
Postgres with PostGIS geometry holds every zone and corridor. The app reads live; the editor writes via typed RPC functions.
OpenStreetMap fetch → crime-density (KDE) scoring → zone/corridor classification → staging → promotion to live.
A second-opinion review pass flags questionable classifications for a human before anything reaches drivers.
Versioned SQL migrations keep the database reproducible; TestFlight distributes builds to testers.
Three repos, one system
Crime and map data flow through a pipeline, get reviewed, then go live for the app to read.
The routing model
The routing logic isn’t a black box — it’s a small set of explicit, tunable rules that decide when a detour is worth it and when it isn’t.
| Risk bands that detour | Red & orange only — yellow is shown, never forced |
|---|---|
| Route sampling | Every 3rd coordinate, ray-cast vs. all active zones |
| Corridor snap tolerance | ≈ 650 m (pass-through detection) |
| Max lateral deviation | 15% of route length, capped at 5 km |
| Corridor search radius | Within 8 km of the danger area |
| Bypass waypoints | Up to 2 injected per route |
| Detour reject rule | > 30% longer than direct → serve direct, flagged |
| Time bands | Day 05–18 · Evening 18–22 · Night 22–05 |
Data model
Polygons with a name, city, three time-band risk levels, crime types, and a source. Soft-deleted (never hard-deleted) so history is recoverable.
red · orange · yellow
LineStrings with a buffer width that mark roads as safe (preferred when threading past risk) or danger (actively avoided). Identity is always (city, name) — road names repeat across metros.
safe · danger
Geometry is stored as PostGIS and written through ST_SetSRID(ST_GeomFromGeoJSON(…), 4326) RPCs, since PostgREST can’t auto-cast GeoJSON to geometry.
Coverage
Live across Gauteng (Johannesburg, Pretoria, the East & West Rand) and Cape Town. Mapped metros: Johannesburg · Pretoria · Cape Town · East Rand · Secunda — and adding a new city is a documented, repeatable runbook, not a rewrite.
We’re always glad to talk shop — or to find sponsors who want to fund the next metro.