← Dev log

frontend

A map of a place, not just a map

A map of a place, not just a map

Web runs Leaflet over any raster tile server — no API key, no billing, no vendor SDK weight. Native runs react-native-maps plus expo-location, on the platform's own map provider underneath.

Themed tiles. Default OSM tiles are light-only and visually loud — they fight a design system. The CARTO tile servers (voyager for light, dark_matter for dark) are free, muted, and sit under brand colours instead of competing with them. Swap the tile URL when the dark-mode class toggles and the map is themed in two URLs, no custom styling pipeline.

Signature pins. Leaflet's divIcon accepts arbitrary HTML/SVG, so a pin can be the product's own geometry — hue-coded by category — instead of the default teardrop. Worth designing three states: drop-in entrance (scale up with overshoot, staggered so the map visibly builds), selected (scale plus a ring), and clustered (a count in the pin). The stagger reuses the same motion tokens as the rest of the app — the map is a screen, not an embed.

Lock it to the region. maxBounds plus a min/max zoom range. That turns "a map" into "a map of this specific place" — users can't scroll to the Atlantic, tiles outside the region never load, and it reads as deliberate rather than generic.

Performance. Lazy-load the map chunk with React.lazy — Leaflet is heavy and can't sit in the landing bundle's critical path. Render a lightweight silhouette placeholder until hydration. Keep LCP on the headline overlay, not the tiles. Batch marker mounting past roughly a hundred pins; the staggered entrance doubles as a mount throttle.

Geolocation permission is the difference between delight and hostility. Never request on load — only on an explicit tap of a clearly labelled affordance. Denial and timeout are silent, falling back to the default regional centre with no toast and no re-prompt; the feature is an upgrade, not a requirement. On grant, do something visibly worth the permission immediately — fly the camera, show a pulsing position marker, surface a derived fact like "6 locations within 5 km" — so the payoff justifies the ask retroactively.

The meta-lesson: both map stacks were already installed and shipped before the redesign — Leaflet hidden behind a secondary toggle on web, react-native-maps entirely unused on the mobile landing screen. The flagship "new" landing feature was mostly promotion of existing, buried capability. Audit installed dependencies against rendered screens before writing anything new.