A personal GPX viewer PWA. Drop .gpx files, view them on 7+ free basemaps
(OpenTopoMap, IGN Plan v2, IGN Ortho, IGN SCAN 50 vintage 1950, OSM, CyclOSM,
Esri satellite, plus optional MapTiler vector styles), draw new routes on
trails, record live traces, and install to your phone as an offline app.
Editorial design, cream + indigo palette, motion-driven interactions, zero backend by default — your data stays in your browser's IndexedDB.
npm install
cp .env.example .env.local # then edit GPX_SOURCE_DIR
npm run sync # copies your folder into public/gpx + builds manifest
npm run dev # http://localhost:3000Point GPX_SOURCE_DIR at your GPX folder:
GPX_SOURCE_DIR=/absolute/path/to/your/GPX
npm run predev and npm run prebuild re-run the sync automatically.
npm run sync:watch auto-refreshes the manifest while you edit your folder.
- Sidebar library with search (
⌘K), activity filter, sort by name / distance / gain / date / rating, difficulty chip, stars. - 7+ basemaps switchable at runtime — OpenTopoMap, IGN Plan v2, IGN Ortho, IGN SCAN 50 (1950 vintage), OSM, CyclOSM, Esri World Imagery, plus MapTiler vector styles when a key is set. (IGN SCAN 25 Touristique moved behind a paid key in 2024 — Plan v2 is the free hiking equivalent.)
- 3 overlays: Hiking routes, Cycling routes, AWS Terrarium Hillshade.
- 3D terrain with adjustable exaggeration (1×–3×).
- Track color modes: Solid, By slope (green→red), By pace (sage→terra when timestamps are present).
- Multi-track overlay: ⌘/Ctrl-click extra sidebar rows to compare routes.
- Compare view: side-by-side elevation with a km / % route toggle and Δ Distance / Δ D+ / Δ D− / Δ time strip.
- Hover sync: hover the elevation chart → marker on the map (and vice versa).
- Keyboard shortcuts:
⌘Klibrary search,⌘⇧Fgeo search,1..9focus the Nth visible track,Ltoggle sidebar,Escclear selection. - Geo search palette (Nominatim, no key) — jump the map to any place on Earth. Fits bounds when the hit is a city / region, flies to point otherwise.
- Drag-and-drop GPX (added to the library) or JPEG/HEIC photos (dropped as indigo pins at their EXIF GPS coords).
- Route builder: pick a routing profile, click waypoints on the map, BRouter snaps them to real trails, close-loop toggle, undo/redo, save to library or download as GPX.
- Live GPS recording: Start / Pause / Resume / Stop; Wake Lock keeps the screen on; 10 s coalesced IndexedDB writes so a phone lock never loses the hike; save as track or download as GPX.
- Multi-day trips: build itineraries from library tracks, drop overnight pins, export as one GPX with per-day tracks and waypoints.
- Weather at trailhead via open-meteo (no key), 1 h IndexedDB cache.
- Difficulty auto-classifier (Easy / Moderate / Hard / Expert) from Naismith-adjusted hiking time.
- Nearby POIs: refuges, springs, peaks, cols, viewpoints — pulled from OSM Overpass, cached one week.
- Track notes, rating, tags per track (IndexedDB, autosaves 350 ms).
- Snapshot export: PNG of the current map + track title + stats.
- Merged GPX export of the current selection.
- Shareable URL: encodes tracks + basemap + overlays in the hash.
- Offline PWA: install to home screen. Save-region-offline pre-fetches basemap tiles + active overlays + the GPX bytes for the focused track (zooms 10–15).
Editorial cream + indigo palette (both anchors from randoma11y, display-P3):
cream-100 #FDF5C9 canvas
indigo-600 #101499 primary
ink #0A0D66 text
sage / amber / terra — reserved for data (D+/D-, difficulty, warnings)
Fonts: Inter (body) + Fira Code (numerals) via next/font/google.
Motion primitives (lib/motion.ts) power the shared spring feel.
The design system is checked in at
design-system/gpxmap/MASTER.md.
Free MapTiler key (100k requests/month) → .env.local:
NEXT_PUBLIC_MAPTILER_KEY=YOUR_KEY
Two extra basemaps (Outdoor, Streets) appear in the Layers picker.
- Next.js 15 (App Router) · TypeScript · Tailwind CSS
- MapLibre GL JS 5 — raster + vector styles, 3D terrain, GeolocateControl
- Recharts — elevation profiles, per-track gradient areas
- Serwist — service worker + tile cache (
@serwist/next) - motion.dev — shared springs, stagger, whileTap
- idb-keyval — IndexedDB persistence
- @tmcw/togeojson — GPX → GeoJSON
- exifr — photo EXIF (2.7)
- BRouter — hiking-mountain routing (2.6, no key)
- Nominatim — geocoder (2.11, no key)
- Overpass API — POIs (2.8, no key)
- open-meteo — weather (2.3, no key)
Everything except MapTiler is keyless and free. Nothing is sent to a backend you don't control.
- Level 1 (10/10) ✅ — foundation UI (multi-track chart, PWA icons, slope color, waypoints, keyboard shortcuts, delete + undo, ...).
- Level 2 (11/11) ✅ — incremental features (difficulty classifier, weather, exports, notes/tags, offline caching, pace overlay, POIs, screenshot, compare view, geo search, photos).
- Level 3 — bigger capabilities (3D terrain ✅, route builder ✅, trips ✅, live recording ✅). Still open: AI trip descriptions, Strava import, cloud sync, accounts, public share pages.
- Level 4 — visual redesign ✅ (editorial cream + indigo, motion.dev, Inter + Fira Code).
See the pinned Roadmap issues for the full status.
MIT. See LICENSE.