Files
rippr/docs/ui-redesign/UI-09-monochrome-dark-map-tiles.md
uhryniuk 3e7878b6e1 Add UI-09: monochrome dark map tiles
Today's OSM tiles are the default tan/cream basemap, which looks nothing like the mockups regardless of HUD styling. Recommends switching to CARTO's free Dark Matter raster tiles over a client-side color filter on OSM tiles, since the mockups depend on the map itself being dark, not just tinted.

Flags a real interaction with V3-11's offline tile cache: it's keyed by (z,x,y) with no provider tag, so switching tile sources without a cache-busting step would silently serve stale OSM tiles under CARTO's URL. That's folded into this ticket's implementation, not left as a followup bug.
2026-08-23 18:29:59 -05:00

5.7 KiB

UI-09 — Monochrome dark map tiles

Depends on nothing · Size S · Status Not started

Goal

Replace the tan/cream default OpenStreetMap raster style with a monochrome dark map, so the map actually looks like it belongs in a dark-mode HUD instead of a light basemap punched through a dark overlay.

Context

RideMap, the Plan/Route Planning canvas, and every Stitch mockup all assume a dark or near-monochrome map underneath the HUD. Today's TileLayer (ride_map.dart) points at tile.openstreetmap.org, OSM's standard light/tan default style — the actual on-device result is nothing like the mockups, regardless of how dark the chrome on top of it is.

This affects every screen that shows a map (Map HUD, Plan, Route Planning, and UI-01's dimmed background on every other tab), so it's worth settling once, early, rather than each screen ticket discovering the same mismatch independently.

Design

Two real options, not one obvious answer:

Option A — switch tile provider to CARTO's "Dark Matter" basemap. https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png (subdomains a-d, retina {r} variant available, max native zoom 20). Purpose-built dark, desaturated/monochrome cartography — closest to the mockups with the least engineering. Free for reasonable usage same as OSM's own tiles, but it's a different third party with its own usage policy and attribution requirement ("© OpenStreetMap contributors © CARTO", not just OSM's own attribution) — a real dependency to add, not a style tweak.

Option B — keep OSM tiles, apply a color filter client-side. Wrap TileLayer in a ColorFiltered widget using a ColorFilter.matrix that desaturates and inverts/darkens the tan basemap into a monochrome dark look. No new third party, no new attribution, and V3-11's offline tile cache keeps working against the exact tiles it already knows about — but the result is a filtered light map, not tiles actually designed for dark presentation, and will read as slightly "off" next to CARTO's purpose-built version (road/building contrast tuned for light backgrounds doesn't always invert cleanly).

Recommendation: Option A. The mockups' whole aesthetic depends on the map itself being dark, not just tinted dark, and CARTO's dark tiles are a well-established, free, no-API-key option already widely used in the Flutter/Leaflet ecosystem for exactly this. The added attribution line and a second host to trust are a small, one-time cost.

V3-11 interaction: the offline tile cache (FileTileCache/CachedTileProvider) is already keyed by TileKey(z, x, y) with no provider-specific data baked in — but that means a cache built against OSM tiles and a cache built against CARTO tiles are indistinguishable to the cache despite being visually different. Switching providers without a plan here would silently serve stale, wrong-looking cached OSM tiles once CARTO's URL is live. This needs a cache-busting or provider-tagging fix as part of this ticket, not a separate one — see Implementation.

Implementation

  1. Add a provider-qualified cache key (or a cache-version bump that invalidates existing V3-11 cache contents wholesale) so switching tile sources can't silently mix cached tiles from two visually different sources.
  2. Update RideMap's TileLayer (and the Route Planner's separate TileLayer instance — see route_planner_screen.dart) to CARTO's dark tile URL template, correct subdomains, and maxNativeZoom: 20.
  3. Update the attribution requirement — check whether flutter_map's RichAttributionWidget/AttributionWidget is in use anywhere already, or add one; OSM-only attribution is no longer sufficient once CARTO tiles are in the mix.
  4. Update tileUserAgent/any OSM-specific comments in ride_map.dart that assumed OSM's tile servers specifically (the "respect OSM's usage policy" reasoning still applies in spirit to CARTO's own policy, but the specific server being addressed changes).
  5. Re-verify V3-11's tile math/download flow still works end-to-end against the new URL template (tile enumeration and caching are provider-agnostic already; only the fetch URL construction needs updating).

Acceptance criteria

  • The map renders in a dark, desaturated/monochrome style matching the Stitch mockups, not OSM's default tan basemap
  • Correct attribution for both OpenStreetMap and CARTO is shown wherever the map is shown
  • Switching tile providers does not silently serve stale, visually-mismatched cached tiles from before the switch (V3-11's cache is invalidated or provider-tagged)
  • Both RideMap and the Route Planner's independent TileLayer are updated consistently — one dark style everywhere, not just on the screens that happened to get touched first

Tests

  • Existing ride_map/route-planner widget tests updated for the new tile URL and still passing
  • Unit: cache-key/versioning change is exercised the same way V3-11's eviction tests are — a cache built under the old scheme does not get served for the new provider

Risks

  • A second third-party tile host is a real dependency, not a free color swap — its own usage policy, its own risk of being blocked if misused, and its own attribution obligation. Treat it with the same care V3-11 already applies to OSM (rate-limit respecting, no bulk prefetch, real user agent).
  • If CARTO's free tier ever proves insufficient or is discontinued, Option B (a color filter over OSM tiles) is the fallback with no new third-party dependency — worth keeping in mind as a documented Plan B, not re-deriving from scratch later.

Out of scope

A fully custom/self-hosted vector tile style — much larger scope, and not needed to hit "looks like the mockups" today.