A navigational tool to rule them all, right in the browser.
No API keys, no registration, no app stores and no invasions of privacy.
A loveletter to the OpenStreetMap ecosystem ❤️ Special thanks to OpenFreeMap for tile hosting.
Note
The app is currently in SPA front-end only mode — the account, maps and collections features (which require a backend) are disabled in the UI.
- Detailed, free global map — no install, no account
- Globe view on first load
- Corner controls for menu, locate and record, plus a merged Info panel (share links, app info, privacy)
- GPS locate with compass heading
- Record GPS tracks and export as GPX
- Import GPX routes and navigate offline
- Download map regions for offline use (via a service worker)
- Multilingual — follows your device language
- Shareable camera views
- Map view persisted between sessions
- Light and dark mode, following your device setting
- Works on any device
Note
Offline maps — drag a region on the map to download its tiles and glyphs for offline use. A hand-rolled service worker (public/sw.js) caches the app shell and map resources; see docs/12.offline.md.
- Location permissions are required for GPS/Compass features. Some users have a deny-all approach to browser permissions and changing them varies between browsers and devices.
- The app does not work in the background or when the device is locked — a common limitation of web apps.
- The app requires an initial connection to load assets and map tiles, even though it works offline thereafter.
- Much more language support
- Better handling of denied location permissions
| Component | Source |
|---|---|
| Map Data | © OpenStreetMap contributors |
| Tile Hosting | OpenFreeMap |
| Rendering | MapLibre GL JS |
| Tile Schema | OpenMapTiles / OSM Bright |
| User Interface | Vue JS / Bootstrap |
npm installnpm run buildSet the backend API origin for cross-subdomain auth/API calls:
Note
Only needed when the auth/backend features are re-enabled — the app currently runs in SPA front-end only mode.
echo "VITE_API_BASE_URL=https://api.example.com" > .env.localnpm run devnpm test # unit tests (vitest, < 10 s)
npm run test:e2e -- tests/e2e/{spec}.spec.js # single E2E spec during development
npm run test:e2e # full E2E suite incl. screenshots — local final verificationSee docs/9.testing.md for the testing strategy.
Please use Conventional Commits.
CI's semantic-release job derives versions, changelogs and GitHub releases from commit messages, so a message that does not parse is invisible to the release process.
Format: <type>(optional scope): <description>, e.g. fix(offline): purge stale tile URLs.
| Type | Use for |
|---|---|
feat |
A new feature (minor release) |
fix |
A bug fix (patch release) |
perf |
A performance improvement (patch release) |
refactor |
A change that neither fixes a bug nor adds a feature |
docs |
Documentation only |
test |
Tests only |
ci |
CI configuration and scripts |
chore |
Maintenance that does not fit the above |
build |
Build system or dependencies |
Breaking changes use ! after the type/scope (feat(api)!: …) or a BREAKING CHANGE: footer, and trigger a major release. See docs/13.ci.md for the full release flow.
See docs/README.md for the full developer documentation.

