DEV Community

Amanuel Demissie for Inside GusLift

Posted on

Week 7: How GusLift Shows Your Route in Real Time

#reactnative #maps #crossplatform #mobiledevelopment

Every ride request involves two locations. The matching screen was showing those as text. Adding a map that actually shows both pins — pickup in green, dropoff in red, other participants in blue — is a small change in concept but a surprisingly tricky one in practice.

Here's how we got there.

The Native Maps Dead End

The first attempt used react-native-maps backed by Google Maps. It worked on iOS and Android simulators. It didn't work on web at all, and the native build requires an API key wired into the native layer, which adds friction every time someone clones the repo. After getting it running, we ripped it out entirely.

What We Replaced It With

The map is now a WebView embed running Leaflet over OpenStreetMap tiles. On web it renders as a plain <iframe srcDoc>. On iOS and Android it uses react-native-webview. Same HTML, same behavior, no API key required, no native build step.

The map HTML is generated at runtime. We compute a bounding box from all the pins, set the center and zoom dynamically, and inject the markers as JavaScript into the Leaflet page before it loads. Each pin is a custom SVG — a teardrop shape with a white circle — colored by role.

The Coordinate Layer

Campus buildings don't have addresses that geocoding handles well. We precomputed lat/lng for all 20 Augustana buildings from OpenStreetMap and stored them in a static lookup table — campusCoords.js. Every pin resolves through that table. No geocoding at runtime, no API call, no latency.

Where Maps Appear

RouteMap is a single reusable component that takes pickup, dropoff, and an optional extraMarkers array. It appears on:

  • The rider and driver waiting rooms (your own route while you wait)
  • The ride detail screens (confirmed route after match)
  • The available riders/drivers screens (driver sees all rider pickup pins; rider sees the driver's pickup pin in purple once matched)

The matching worker was extended to broadcast pickup_loc alongside to_location over WebSocket so that map pins for other participants are available on match screens without an extra DB fetch.


What Didn't Change

State, matching logic, and the Durable Object model are untouched. The map is purely display — it reads locations already present in the app state and renders them.

Top comments (0)