Architectural Decision Record: Mapping¶
Status: Proposed
Date: 2026-07-19
Candidates Evaluated: MapLibre GL JS, PMTiles, OpenFreeMap, OpenMobileMaps
1. Problem Owned¶
The application requires a GPU-accelerated map renderer capable of displaying vector tiles, overlaying domain-specific layers (streamflow gauges, flood zones, fishing access points, bathymetry), and operating 100% offline on iOS Safari and Android Chrome when the user is in remote areas of Maine with no cell signal.
2. Evaluation Summary¶
We evaluated four candidate tools. Three form a complete integrated stack. One was immediately disqualified.
OpenMobileMaps — Rejected immediately. OpenMobileMaps is a native C++ SDK with iOS/Android rendering backends. It cannot run in a browser or PWA. With ~214 GitHub stars and low activity, it is also not a viable upstream candidate for any part of the platform. It is removed from further consideration.
The remainder of this ADR addresses the three-tool stack: MapLibre GL JS + PMTiles + OpenFreeMap.
3. How the Three Tools Compose¶
┌──────────────────────────────────────────────────────────────┐
│ MapLibre GL JS (Rendering Engine) │
│ ↓ Requests tiles via pmtiles:// protocol │
├──────────────────────────────────────────────────────────────┤
│ PMTiles JS Client (Data Retrieval) │
│ ↓ Reads byte ranges from local file │
├──────────────────────────────────────────────────────────────┤
│ OPFS (Origin Private File System) │
│ ← maine.pmtiles file stored here (20–30 MB estimate) │
├──────────────────────────────────────────────────────────────┤
│ OpenFreeMap Style JSON (Visual Design Layer) │
│ ↓ Defines how vector features are rendered │
├──────────────────────────────────────────────────────────────┤
│ Bluefly Fishing Layers (Domain Intelligence) │
│ ← USGS nodes, NWS flood zones, access points, bathymetry │
└──────────────────────────────────────────────────────────────┘
4. Measured Evidence¶
| Metric | MapLibre GL JS | PMTiles | OpenFreeMap |
|---|---|---|---|
| License | BSD-3-Clause | BSD-3 / CC0 spec | MIT |
| GitHub Stars | ~11,100 | ~3,000 | ~5,600 |
| Governance | Linux Foundation (MapLibre Org) | Protomaps (open spec) | Single maintainer |
| Offline Capability | Yes — requires SW-cached assets | Yes — OPFS byte-range reads | Style assets only; tiles require PMTiles |
| PWA / iOS Safari | Yes (WebGL supported iOS 15.2+) | Yes (OPFS supported iOS 15.2+) | Yes |
| PWA / Android Chrome | Yes | Yes | Yes |
| Render approach | WebGL / WebGPU | Protocol adapter to MapLibre | Style JSON |
| Data independence | Yes — data agnostic | Yes — format only | Yes — can point to any tile source |
| Online requirement | No | No | Style & glyphs require local bundling |
5. Upstream Ownership (Per Tool)¶
MapLibre GL JS owns: - GPU-accelerated tile rendering pipeline - Vector tile (MVT) parsing - Camera navigation, gesture recognition (pinch, rotate, drag) - Worker thread orchestration for tile processing - Text rendering along paths, label collision detection
PMTiles owns:
- Single-file archive format for all map tiles
- pmtiles:// protocol registration inside MapLibre
- Byte-range fetch logic (reads only the viewport-required bytes from OPFS)
- CLI tooling to compile OSM extracts → .pmtiles
OpenFreeMap owns: - Pre-built cartography style sheets (Liberty, Positron, Bright) - Font glyphs and icon sprites - Weekly OSM tile compilation and public CDN hosting (for online use)
6. Ownership Result¶
| Capability | Owner |
|---|---|
| GPU tile rendering pipeline | MapLibre GL JS |
| Touch gesture handling | MapLibre GL JS |
| Tile archive format & byte-range reads | PMTiles |
| Offline tile storage (OPFS management) | Bluefly |
| Tile download + storage quota management | Bluefly |
| Base cartography visual design | OpenFreeMap |
| Font glyphs and sprites (bundled locally) | OpenFreeMap (bundled) |
| Style customization (brand colors, dark mode) | Bluefly |
| Fishing domain overlays (USGS, NWS, access) | Bluefly |
| Elevation / contour overlay | Bluefly (USGS DEM → PMTiles) |
| React component lifecycle management | Bluefly |
| PWA Service Worker cache configuration | Bluefly (Serwist) |
7. Remaining Bluefly Work¶
After adopting the full stack, Bluefly owns a clearly bounded set of implementation tasks:
- Local Assets Pipeline: Download OpenFreeMap style JSON, glyphs, and sprites into
/public/map-assets/. Edit style JSON to reference local paths instead of CDN URLs. - PWA Cache Config (Serwist): Add map asset paths to the Service Worker cache manifest so all fonts, icons, and style assets are available offline.
- OPFS Download Orchestration: Implement the UI to download the Maine
.pmtilesarchive (~20–30 MB) into OPFS, with progress indication and storage quota checks. - Fishing Domain Layers: Build GeoJSON overlays for USGS streamflow gauge nodes, NWS active flood zones, and manually curated fishing access points.
- Elevation Overlay: Compile USGS Digital Elevation Model data for Maine into a Terrain-RGB PMTiles set for contour lines and relief shading. This addresses the known gap in OpenStreetMap's rural coverage.
- React Integration: Manage the imperative MapLibre instance lifecycle inside React hooks (client-side only, loaded via
next/dynamicwithssr: falseto prevent hydration errors).
8. Known Gaps in Upstream Data¶
These are gaps in the OSM-derived data that Bluefly will need to address with domain-specific curation: - Logging roads and forest access tracks — often unmapped or misclassified in OSM for rural Maine - Contour lines / elevation — not included in standard OSM vector tiles; requires a separate USGS DEM compilation - Private fishing access points — by design, never in OSM (ethical constraint)
9. Decision¶
Adopt: MapLibre GL JS + PMTiles + OpenFreeMap as the complete offline mapping stack. Reject: OpenMobileMaps (native SDK, incompatible with PWA architecture).
The three-tool stack is complementary by design. MapLibre owns the rendering. PMTiles owns the offline storage format. OpenFreeMap owns the base cartography. Together they eliminate every layer of custom map infrastructure. Bluefly's remaining work is limited to domain-specific overlays, OPFS orchestration, and style customization — exactly what should be owned by the domain.
10. Record Frozen¶
This document is an architectural decision record. The comparison phase is complete. Future mapping work — fishing overlays, elevation tiles, OPFS download UX — is tracked as implementation tasks, not revisions to this ADR.