Repository navigation
Description
What problem would this solve?
Offline areas keep the map visible without a network, but the installed app still needs the server for every route. Someone driving through a rural area without coverage, or hiking in a valley, can follow a route they planned earlier, but cannot plan a new one. If they leave the route, the app cannot calculate a replacement until the network returns. Offline maps without offline routing stop being useful at exactly the moment they are needed.
What would you like to be able to do?
In the installed Android app, downloading an area also downloads what is needed to route inside it. Without a network, I can then plan a driving, walking or cycling route between any two points in my downloaded areas, start guidance, and get a new route automatically when I leave it. When the network returns, the app goes back to server routes, which include live traffic, closures and road conditions.
Verified current state
Checked against main at e68106f on 3 November 2026.
- Offline mode cannot calculate a replacement route. An offline package is a PMTiles map archive plus glyphs and has no routing data. It lives in the web page's IndexedDB, which native code cannot read.
- The instance routes with Valhalla 3.9.1, built from the same OSM extract as the map. The Valhalla provider's
transformTripmaps a Valhalla trip to the shared route contract, including maneuvers, lanes and signs. - The app's native navigation requests a reroute through a remote-work port, which calls the server's directions API. feat(mobile): run native ground and transit navigation in the installed app #758 wires that port into the running app. A failed request leaves the session off-route until the network returns.
Approach
- Choose the engine (first, short step). The default candidate is Valhalla on the device: it is the engine the instance already runs, so device routes can reuse
transformTrip, match server routes, and use tiles cut from the instance's own build. Confirm a working Android build (valhalla-mobile or our own NDK build), its size, memory use and route latency on a mid-range phone, and the licences of Valhalla and every bundled library. Consider OsmAnd/OBF only if Valhalla misses the budgets; its GPL-3.0 licence and different maneuver model must be weighed explicitly. Record the decision in the developer docs before integration code lands. - Routing packages on the server. When an area is prepared, data-manager also cuts the Valhalla tiles that intersect its bounds from the instance's built tiles. The result is a separate, immutable artifact next to the PMTiles, with its own manifest: coverage, Valhalla and data versions, bytes, SHA-256 and attribution. The capability endpoint states whether routing packages are available, so the page never infers offline routing from map coverage.
- Native installation. The shell downloads, verifies and stores routing packages in app storage, not in the WebView. It ties their lifecycle to the area: install with it, delete with it, and replace when the dataset version changes. New bridge messages, with a protocol bump, let the page install a package, read its state and remove it.
- Plan routes offline. When the network or the directions API is unavailable, the page asks the shell for a route. The shell runs the engine and returns routes in the shared contract. The page shows them as offline routes: no live traffic, closures or road-condition alerts, and clearly labelled.
- Reroute offline. The reroute port tries the server first. If the request fails for network reasons and the position is covered, it answers from the device engine. Server answers stay preferred whenever they arrive.
- Docs, compliance and UI. Update the user and developer offline docs, the dependency inventory, the licence notices and the store data practices. Show routing coverage separately in the offline list.
Out of scope: iOS (a follow-up once Android ships), transit routing offline, live data offline, a planet or country-wide download, and replacing MapLibre.
Acceptance criteria
- The engine decision, version, build and licences are documented, and the dependency inventory passes.
- Downloading an area in the installed Android app also installs its routing package. The offline list shows routing coverage separately from map coverage, and removing the area removes both.
- In airplane mode, a never-cached driving, walking and cycling route between two points inside downloaded areas is planned, shown and guided natively.
- In airplane mode, a deliberate deviation produces a new route within an agreed time budget, and guidance continues.
- Device routes use the shared route contract, with German and English maneuvers and voice instructions, and are marked as offline.
- A route that leaves the downloaded coverage fails with a clear message instead of a partial route.
- Missing, corrupt or outdated packages, an interrupted download, low storage, cancellation and an app restart mid-route are each handled without leaving a broken package or a stuck session.
- Package size, install time, route latency and memory are measured on a mid-range Android phone against budgets agreed before rollout.
- When the network returns, the next reroute uses the server.
- User and developer docs, screenshots and a short recording of an offline reroute are included.
- Store metadata may describe offline routing only once it ships; the forbidden-claims test is updated at the same time.
Verification approach
Use repeatable network-denied runs on a real Android phone, deterministic deviation fixtures, and fault injection for package installation. Compare device and server routes for a small pinned corpus. With the same Valhalla version they should differ only where live data applies.
Dependencies and decisions
- Connect native navigation in the installed mobile app #398 (native navigation) is required. fix(mobile): start the installed app and keep its bridge on Android #756–feat(mobile): draw the app's own screens in the web UI's colours #759 compose it on Android.
- Search downloaded places and addresses without a network #403 (offline search) lets people find a destination by name while offline; without it, they pick one on the map or from saved and recent places.
- Decide during the first step: the engine, the time and size budgets, and whether a routing package can be added to an area downloaded before this feature existed.
Alternatives or workarounds
Plan the route online and follow the saved snapshot: this works today, but any deviation strands the user. A full country graph on the device: simpler, but too large for most phones. An OsmAnd-based engine: a viable fallback if Valhalla on Android misses the budgets.
Additional context
Ownership and status
Maintainer-owned backlog. On 3 November 2026 this was rewritten from a prototype-only task into the feature itself; choosing the engine is its first step.
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Effort
Activity
[-]Prototype Android offline route planning and rerouting[/-][+]Plan routes and reroute without a network in the Android app[/+]