Skip to content

TimInTech/gpx-pwa

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

37 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GPX Tracker

A modern PWA for visualizing and analyzing cycling tours. Import GPX files, explore your ride history on an interactive map, spot duplicates, and review stats — all in the browser, offline-capable.

Tech stack icons

Features

  • GPX import — drag & drop or file picker, batch import (100s of files at once)
  • Deduplication — automatically detects identical rides imported multiple times
  • Interactive map — dark CartoDB basemap rendered via MapLibre GL (WebGL)
  • Heatmap mode — density heatmap showing your most-ridden areas
  • Route visualization — per-route color, visibility toggle, click-to-select
  • Yearly / monthly stats — distance, elevation, count with bar charts
  • Year filter — quickly scope the map and stats to a single year
  • Offline — Service Worker caches app shell + map tiles (CartoDB Dark)
  • PWA installable — runs as a standalone app on desktop and mobile

Getting Started

Requirements

  • Node.js ≥ 20
  • npm (or pnpm)

Development

npm install
npm run dev     # bundles GPX worker + starts Next.js dev server

Open http://localhost:3000.

Production build

npm run build
npm run start

Docker

docker-compose up --build

Tests

npm test          # Vitest unit tests
npm run e2e       # Playwright E2E (requires running server on :3000)
npm run test:all  # both

Architecture

app/
  page.tsx              Full-screen layout: collapsible sidebar + MapLibre map
  api/sw/route.ts       Service Worker (offline fallback, tile cache)

components/
  map/map-container.tsx MapLibre GL map — routes, heatmap, selection
  sidebar/sidebar.tsx   Route list, year filter, search, sort
  sidebar/route-card.tsx Per-route card with color picker + delete
  sidebar/stats-panel.tsx Distance/elevation totals, yearly/monthly bars
  import/dropzone.tsx   Drag & drop import UI with progress + error reporting

lib/
  types.ts              Core types (Route, RouteStats, MapMode …)
  store.ts              Zustand global store + selectors
  gpx/parse.ts          GPX XML parser (RDP simplification, stats, dedup fingerprint)
  gpx/dedup.ts          Route fingerprinting and duplicate detection
  gpx/parse.worker.ts   Web Worker entry point (bundled → public/parse.worker.js)
  storage/db.ts         IndexedDB storage via idb

Key design decisions

Concern Choice Why
Map rendering MapLibre GL JS WebGL, native heatmap, fast with 1000s of points
Basemap CartoDB Dark (raster) Free, no API key, dark look that makes routes pop
State Zustand Minimal, avoids prop-drilling across map + sidebar
Parsing Web Worker + fast-xml-parser Non-blocking UI even for large GPX batches
Storage IndexedDB (idb) Browser-native, works offline, large capacity
Dedup Coordinate fingerprint Start/mid/end snapped to ~110m grid + distance bucket

Data stays local

No server, no account. All GPX data is stored in the browser's IndexedDB. The only external requests are map tile fetches from CartoDB (cached by the Service Worker).

License

MIT

About

GPX Route Manager PWA – Import, dedupe & visualize GPX routes; offline-first, Docker-ready, Next.js + TypeScript.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages