Route optimizer for field technicians and service/delivery crews. Import a list of stops, get back an efficient driving order, and open it in your maps app of choice.
Ships as two native apps sharing one core library:
- Desktop — a three-panel egui GUI for Linux, Windows, and macOS.
- Android — a
NativeActivityapp with a Slint UI, distributed via Google Play and F-Droid.
The Android app, recorded from the current build: adding stops on Home, the Results page, and Settings.
Watch the full video preview (MP4)
The desktop app, recorded from the current build: adding the same five stops on Home and optimizing the route.
Watch the desktop preview (MP4)
Quick Start
Get ONTrack from the GitHub Releases page — the latest release is v2026-09-10.
- Android phone — get the app from the releases page.
- Windows desktop — download ontrack-windows-x86_64.zip from the v2026-09-10 release.
Developer info
git clone https://github.com/qompassai/ontrack.git
cd ontrack
# Build and run the desktop GUI
cargo build --release -p ontrack-desktop
./target/release/ontrack
# Run the core library's tests
cargo test -p ontrack-coreCrates
| Crate | Type | Description |
|---|---|---|
ontrack-core |
library | Address parsing (CSV/XLSX), geocoding (Nominatim/Google), distance matrix (haversine/OSRM/Google), nearest-neighbor + 2-opt TSP solver, export URL builders, optional on-device Whisper voice input |
ontrack-desktop |
binary (ontrack) |
egui desktop GUI — Linux, Windows, macOS |
ontrack-mobile |
cdylib + Android app | NativeActivity + Slint UI, built with cargo-ndk and packaged with Gradle |
Solver
Nearest-neighbor seed + 2-opt local search — pure Rust, no C++ FFI, no OR-Tools. For typical field routes (≤ 50 stops) this produces near-optimal results in well under a second.
| Backend | Algorithm | Quality | Speed (50 stops) |
|---|---|---|---|
| 2-opt (default) | NN seed + 2-opt local search | Near-optimal | < 1s |
| Nearest-neighbor | Greedy NN | Good | < 10ms |
Architecture
ontrack/
├── Cargo.toml # workspace
├── crates/
│ ├── ontrack-core/
│ │ └── src/
│ │ ├── lib.rs
│ │ ├── config.rs # .env / environment loading
│ │ ├── parser.rs # CSV / XLSX address files
│ │ ├── geocoder.rs # Nominatim + Google geocoding
│ │ ├── matrix.rs # haversine + OSRM + Google distance matrix
│ │ ├── solver.rs # nearest-neighbor + 2-opt TSP
│ │ ├── exporter.rs # CSV, Maps URL, FieldMaps, Street View, Waze
│ │ └── voice.rs # optional on-device Whisper voice input
│ ├── ontrack-desktop/
│ │ └── src/
│ │ ├── main.rs
│ │ ├── app.rs # worker-thread app state
│ │ └── views/ # home / results / settings panels
│ └── ontrack-mobile/
│ ├── src/
│ │ ├── lib.rs # android_main entry point
│ │ ├── controller.rs # Slint UI wiring
│ │ ├── gps.rs # Android LocationManager via JNI
│ │ └── preview_main.rs # desktop preview of the mobile UI
│ ├── ui/app.slint
│ └── android/ # Gradle project (Play Store + F-Droid)
├── scripts/ # build, sign, emulate, screenshot tooling
├── fastlane/ # Play Store release automation
├── fdroiddata/ # F-Droid metadata recipe
└── playstore/ # Play Console listing metadata
Configuration
Copy .env.example to .env in the repo root:
cp .env.example .envGOOGLE_MAPS_API_KEY="" # optional — enables Google geocoding/distance matrix + Street View
OSRM_BASE_URL="http://router.project-osrm.org"
ARCGIS_ITEM_ID="" # optional — your ArcGIS Online web map ID, for FieldMaps deep links
ONTRACK_WHISPER_MODEL="base"GOOGLE_MAPS_API_KEY — optional; only needed if you want Google for geocoding and driving distances instead of the free backends below.
- In the Google Cloud Console, create or select a project.
- Enable the Geocoding API and the Distance Matrix API for that project.
- Go to APIs & Services → Credentials → Create credentials → API key.
- Recommended: restrict the key to those two APIs, so it cannot be used for anything else.
Full walkthrough: Google’s Get API key guide.
ARCGIS_ITEM_ID — not an API key. It is the ID of your own ArcGIS Online web map, used to build Field Maps deep links.
- Sign in to ArcGIS Online (a free account works) and create or open your web map.
- Open the map’s item details page.
- The item ID is the
id=value in the page URL — copy it into.env.
See the ArcGIS Online item details documentation.
Free backends — no key at all. Nominatim geocoding and the public OSRM router (OSRM_BASE_URL) work without an account. If you send heavy traffic, respect the Nominatim usage policy or self-host OSRM instead.
ONTRACK_WHISPER_MODEL — picks the on-device Whisper model for voice input (for example base). No key and no account.
No API key required. Without one, the app uses:
- Nominatim (OpenStreetMap) for geocoding
- The public OSRM router for real driving distances, or offline haversine distance
- Plain Google Maps / Waze / Apple Maps URL schemes for turn-by-turn navigation
Android build (Play Store / F-Droid)
The Android app is built in two stages: cargo-ndk compiles the Rust core
into libontrack_mobile.so for arm64-v8a and armeabi-v7a, then Gradle
packages it into an APK/AAB. Nothing is committed as a prebuilt binary — both
stores build from source.
# One-shot build (AAB for Play Store, APK for sideloading/F-Droid, or both)
./scripts/build-android.sh both
# Local emulator smoke test (SDK setup, AVD, install, launch, screenshot)
./scripts/acli.sh full ontrack 4See scripts/ for the full Android/emulator/signing toolchain, and
fastlane/ + fdroiddata/ for the store metadata.
Application ID: ai.qompass.ontrack
Apache License 2.0 — see LICENSE.md.


