Offline Data Tiles
:::caution Last revised 2026-05-17 — not re-verified
This page has not been checked against the running system since it was
written, and predates a large part of the current product. It is scheduled
for rewrite. For anything about the API, /docs on a running server is
authoritative.
:::
FastGIS packages road curvature data and POI data as 1°×1° SQLite tiles that the mobile app downloads on demand. Once downloaded, searches and map queries work without an internet connection.
What's in a tile
Curvature tiles (curv-tiles/)
Each tile is a small SQLite file covering a 1° latitude × 1° longitude cell (e.g. tile 59_10 = lat 59–60°N, lon 10–11°E).
Every road row in a curvature tile includes:
| Column | Description |
|---|---|
name | Road name |
curvature | Raw curvature score |
distance_km | Road length |
road_type | OSM highway classification |
surface_class | paved / unpaved / unknown |
is_scenic | OSM scenic tag flag |
elevation_range_m | Max minus min elevation along the road |
elevation_gain_m | Total uphill elevation gain |
min_elevation_m | Lowest point |
max_elevation_m | Highest point |
min_water_dist_m | Distance to nearest water body (sea, lake, river) |
water_flags | Bitmask: 1=sea, 2=lake, 4=river |
Elevation data is enriched offline by scripts/enrich_elevation.py using the best available national DEM for each road's location. Water proximity is enriched by scripts/enrich_water_osm.py via Overpass API.
POI tiles (poi-tiles/)
Each tile contains points of interest (fuel stations, campsites, viewpoints, etc.) from the OSM POI database for that cell.
Downloading a country pack
Open More → Storage → Offline packs (also reachable from the Navigate map's offline menu). Each country row installs everything the rider needs offline in one tap — routing tiles, POI and search bundles, curvature data and the basemap region — and shows what is on disk as component chips.
Interrupted downloads resume
Routing packs are large (1–10 GB per country). A download that stops — the screen locks, the app is sent to the background, the connection drops, the app is killed — keeps the part already transferred:
- The row shows Paused — the part already downloaded is kept. Tap to continue. instead of reverting to "not downloaded", and it still says so after a restart.
- Tapping the row again continues from where it stopped. On iOS the resume uses the system download's own resume token, on Android the bytes already written to the partial file; a token older than 24 hours, or one for a pack the server has since rebuilt, is discarded and the download starts clean.
- The automatic clean-up of abandoned download temp files leaves a paused download's bytes alone. Reclaim space in Storage deletes them deliberately, and a paused download then starts from zero.
Deleting a country while another one is installing is refused until the download finishes (or is cancelled): routing packs share one folder, and the delete would take the in-flight files with it.
You can switch to aeroplane mode after downloading to test offline functionality.
A country as one file (Android)
On iPhone the app's folder shows in the Files app. Android has no such view, so the packs sheet does it itself:
- Save as file on an installed country asks where to save (Android's own
save dialog; Download by default) and writes one file,
epona-<country>-<date>.tar.gz. It carries the offline routing, places (POI), search, closed gates and dirt passages that are installed; the map itself lives inside MapLibre's own database and downloads again the next time you are online. Norway with its dirt passages is about 1.4 GB and took about three minutes on a 2018 phone; the sheet shows the progress. - Import a pack file, above the country list, opens such a file — on this phone or on another one you copied it to — and installs it with no connection: the country's routing works offline as soon as it is in.
- The import keeps the download's rules. A country from another build of the offline maps than the ones installed is refused, with the countries to remove named (two builds in one routing folder give wrong routes); every part is checked before it replaces the one installed; a file that is not an Epona pack, or one saved by a newer Epona, is said in words.
Space the app gives back
Deleting or updating a basemap pack leaves its space free inside MapLibre's map database, and the file never shrank on its own: one phone held 12 GB of free space in a 12.7 GB file. The app now gives it back by itself.
- At start, before the map opens, the app compacts the map database when
most of the file is free space and the phone has room for the rebuild. It
checks the file first (
quick_check) and keeps every offline pack. A file too big to compact during a launch is copied compactly in the background while you use the app (never during a download), and the copy replaces the original at the next start, only if your offline packs did not change in between. A file that fails the check is left as it is. - Clear map cache (Svuota cache mappa) in More → Storage shows how much it frees, deletes the maps seen online and leaves the offline packs in place. Free space still left in the file goes at the next start.
- The maps seen online are capped at 50 MB.
- Photos and videos taken in the app were kept twice by the picker. Its copy is now deleted once the capture is saved, and the old copies are swept at start and by Reclaim space. A file that a capture, a note, a queued survey answer or a draft still points at is never deleted.
North Africa
Since 3 October 2026 the routing graph reaches across the Strait of Gibraltar. The Offline packs sheet lists five more countries:
- Morocco and Western Sahara, 0.6 GB of routing tiles (one Geofabrik extract holds both, and its search results keep the "Western Sahara" label);
- Tunisia, 0.3 GB;
- Egypt, 0.7 GB;
- Mauritania, 0.2 GB;
- Senegal and Gambia, 0.2 GB.
Two more joined on 10 October 2026:
- Algeria, 1.3 GB of routing tiles (0.56 GB to download). Its box also takes in the edges of Morocco, Tunisia and Libya, so the pack carries those roads too;
- Saudi Arabia and the Gulf states, 0.9 GB (0.34 GB to download): Saudi Arabia, the United Arab Emirates, Oman, Qatar, Bahrain and Kuwait in one pack. Each search result names its own country ("دبي · Dubai" reads United Arab Emirates).
Each installs like a European country: routing, points of interest, search,
and the map region (from the default vector map). Most Tunisian places are
mapped with an Arabic name (Tataouine is "تطاوين"). The offline search also
knows a place, road or point of interest by its other OpenStreetMap names
(French, English, international and alternative), so "Tataouine" finds the
town, shown as "تطاوين · Tataouine". This holds in every country's search pack
baked since 10 October 2026: a pack installed earlier knows the main name only,
and the Offline packs sheet offers its update. An app built before that day
finds the place too, but lists it under its Arabic name and below the results
spelled in Latin letters. Online search does the same in any language
written in Latin letters: a place with no name in that language, and named
only in Arabic, Greek or Cyrillic, is shown with its English name beside it. Since 3 October's evening
they also carry their dirt passages (see below). The advisory-zone file installs with any country, so the phone's
own router keeps out of the mine and military zones offline too.
An offline route in the region also shows its areas section in the plan sheet, as an online route does:
- the zones it was kept out of;
- the permit zones your event permit opened, with the EVENT MODE banner;
- a stop that lies inside a closed area;
- whether the far zones were left out to keep the request small.
The phone checks the finished route against every zone in the file. A route that still passes a mine, military or permit area is shown in red. When the route ran through such a zone outside the area the request covered, the phone routes once more over a larger area. It keeps the second route only when it passes fewer of these zones and is at most four times as long, the same rule as the server.
Offline, the section lists only mine, military and permit zones, by their names. The other advisory areas, their dangers and their sources are listed on a route planned online.
The advisory areas are one card per zone, folded under one line (Zones on this route: 6); a route along a border that crosses one zone many times gets one card that counts the crossings and gives the first and last km. Tap a card to see that stretch of the route on the map. The red blocks (mines, military areas, a stop inside a closed area) are always open.
A recorded ride in the region lists the closed areas its track passed, under Closed areas on this ride on the ride's page: when you entered and left each one, and whether a permit valid at that moment opened it. It works without a connection.
Since 10 October 2026 they also carry their closed gates. Our OpenStreetMap mirror held Europe only until then; a second one now holds the seven North African countries (the five above, Libya and Algeria) and follows OpenStreetMap's daily changes, like Europe's. A country's install downloads its gate file as a European one does, and the offline router keeps out of the locked and private gates it lists.
Since 10 October 2026 they also have curvy roads: the curvature search, the curvature map layer and the offline curvature tiles cover the five countries, and Algeria, Libya and the Gulf states too. The Tizi n'Tichka on the N9 is one road of 131 km. The Twisty and Mixed presets leave out a road only when it is built up for more than a quarter of its length, so a long road through a village or two stays in: near the pass Twisty lists the N9 and the RP1506, and Mixed adds the RP2016. Offline, the app applies the same rule from the update after 10 October 2026, on curvature tiles downloaded since then; older tiles and older versions of the app leave out any road that passes a crowded spot.
Online, routes also cover Libya, Algeria, Saudi Arabia and the Gulf states, without an offline pack. Every route in the region carries the advisory-zone block. In the seven North African countries an online route also names its closed gates and routes around them. The same mirror gives them what it gives Europe:
- the speed limit of the road you are on;
- the wild camp search, with its water, buildings and roads;
- the scenic stops;
- the roadbook's OSM symbols;
- the match of your rider reports and OSM edits to the road.
Saudi Arabia and the Gulf states are in neither mirror and have none of these yet.
The same rebuild gave every routing pack a new build date. A country you installed before shows update available once; update every installed country, because the phone does not mix packs from two builds.
Storage layout
Tiles are stored in the app's documentDirectory:
documentDirectory/
curv-tiles/
59_10.sqlite ← curvature tile lat 59, lon 10
59_11.sqlite
…
poi-tiles/
59_10.sqlite ← POI tile lat 59, lon 10
…
curvature/
roads.db ← monolithic DB (legacy / pre-tile download)
poi-bundles/
… ← legacy region bundles
Regenerating server-side tiles
When the server's roads database is enriched with new data (elevation, water proximity, scenic scores), the tiles need to be rebuilt:
# 1 — re-enrich the roads database
python scripts/enrich_elevation.py --source auto
python scripts/enrich_water_osm.py
# 2 — rebuild all tiles (--force overwrites existing files)
python scripts/build_curvature_tiles.py --force
python scripts/build_poi_tiles.py --force
# Or rebuild a specific region only (e.g. western Norway)
python scripts/build_curvature_tiles.py --force \
--lat-min 57 --lat-max 64 --lon-min 4 --lon-max 11
After rebuilding, the /grass/tiles/ API immediately serves the new files. Mobile users re-download using More → Storage → Reset app data (tick Routing & data packs), then the Offline packs sheet.
Closed gates offline
A country pack also carries the gates that are closed to motor vehicles — locked, private, forestry-only, or shut by a seasonal rule. The routing engine on the phone cannot read those tags itself, so without this file an offline route could send you at a locked gate.
- The file is small (195 KB for Sweden, 2.1 MB for the Germany region) and installs with the region's routing pack.
- Your phone re-checks it when the app comes to the foreground online, at most once a day, and quietly downloads a newer version.
- Seasonal closures are judged for the date you are riding, so a gate shut from 15 November to 30 April is only avoided inside that window.
- The pack detail shows which OSM date the gate data comes from, and turns amber after 45 days (20 days in April, May, October and November, when gates change most).
- Gates that are open, or merely awkward, are not in the file: those come from the server when you have a connection.
- A country the server has no gate data for (today the Gulf states, which no Overpass mirror holds) installs without it, and its pack detail says No closed-gate data for this region, offline too.
Dirt passages offline
A country pack can also carry its dirt passages — the layer, the passage cards and planning rides through passages with no connection. It is optional and ticked by default: the Dirt passages chip on a country removes it (you are asked first, with its size) or adds it back, and a removal is remembered.
- Two files: the dirt tiles and the passages a plan can use, for the countries that have dirt passages — Norway ≈ 80 + 61 MB, Sweden ≈ 155 + 162 MB, Poland ≈ 210 + 115 MB, Germany ≈ 385 + 225 MB, France ≈ 460 + 135 MB, Austria ≈ 100 + 33 MB, Italy ≈ 250 + 58 MB, Spain ≈ 340 + 150 MB, Portugal ≈ 90 + 47 MB, Luxembourg ≈ 3 + 1 MB; Malta and Andorra under 1 MB each; Morocco and Western Sahara ≈ 85 + 35 MB, Tunisia ≈ 35 + 7 MB, Egypt ≈ 70 + 6 MB, Mauritania ≈ 12 + 7 MB, Senegal and Gambia ≈ 45 + 52 MB. Algeria's passages (since 2026-10-04) are on the map online only: Algeria has no country pack yet. Each country's tiles hold only its own passages. Norway's and Sweden's passages files also hold the dead ends your lifted gaps can open (below), which is why they grew from 7 and 26 MB in October 2026, and since 17 October 2026 each passage's own pieces for the offline dirt track (below; +13 and +32 MB); the other countries' files grow the same way when their next build adds them.
- With the part installed the dirt layer is drawn from your phone even online — faster, and it keeps working in a valley with no signal.
- The map draws every installed country in view, and online the archive of each country whose outline box holds the map centre. Where two boxes overlap (Sweden's covers most of Nordland) both are drawn, so Norway's passages show there; before 10 October 2026 only the smaller box's country was drawn. The curvature layer draws each country under the centre the same way.
- A passage card offline is the full card for any passage a plan can use, marked offline copy (live wetness needs a connection), and for a dead end whose every end reaches the road network across gaps; for the others (the other dead ends, worth-exploring, closed) it is a short card from the map's own data. With the car as the plan's vehicle the cards and Add to plan follow the car's access rules: a motorcycle-only path is not offered, a track only a car may drive is.
- The gaps at a dead end (your Gaps at the dead ends limit) work offline from the installed tiles: the orange gap lines and whether a passage counts as joined. An offline card gives each dead end's longest gap, without the hop-by-hop facts. A warning you lift offline is kept on the phone and sent when you are back online. Tiles installed before 12 October 2026 have no gaps: the pack shows an update.
- A passage card has a Vertical profile button under its gaps. With a connection it measures the passage along its own line (a few seconds on a long one, with a spinner): climb and descent, grade colours, the surface, the two ends (A and B), the gates, and, when your gap limit joins the passage, each gap as a shaded stretch with its length. Between two pieces it follows the paved road (shaded grey); where the passage branches it jumps to the other branch (a thin dotted line, no distance). Drag along it to read a place: a dot follows your finger on the map. Its figures sit beside the card's own; the two read different elevation data (the card a 30 m model, the profile the national one where there is one, Norway's 10 m), so they can differ, and the card says by how much. Every profile you open is kept on your phone: it opens at once the next time, and with no connection it opens from there; the card says saved on this phone, no button needed. A passage you never opened online shows the button greyed, no profile offline.
- Gap groups. From 25 m up, the passages your gap limit joins to each other are one group (Bergen and Bontveitvegen near Bergen from 150 m, not at 100 m). Tap one and the whole group is haloed on the map; change the limit with the card open and the halo follows, and with a paved-gap view on as well the view's group keeps the halo when the passage has one. With a connection the card gains the group block: the passages in riding order (tap one to open its card, the halo kept), one length with its dirt, tarmac and gap metres, the grade, the climb and descent ridden in that order (on the dirt only: the profile also counts the tarmac and the gaps between the passages), the gates across them, and every gap inside the group with its facts, its warning and your lift, the ones the riding path crosses first. Profile of the group fetches the other passages and draws one profile along all of them end to end, across the gaps between them, kept on your phone like a passage's. Add all to plan stays greyed, with the reason: routes still treat these as dead ends — unless your own lifts make every passage of the group routable for you (with a connection, from the app after 15 October 2026): then it adds them, and the plan crosses a gap you lifted as its own leg, ride on sight, where it is shorter than the road; off the line, navigation takes you back to the gap's far side, never into it. Offline it works the same from the passages file, which holds every dead end whose ends all reach the road network across gaps, with the gaps: a passage only your lifts open goes into your plan with no connection too, and the gaps are ride on sight legs (from the app and the passages file of 15 October 2026 on). Where several of your gaps join the same two passages, the phone keeps the one the server keeps: the gap along a mapped path or track, then the shortest (from the app after 16 October 2026 and the passages file of 16 October 2026 on; with an older file the plan weighs every gap as before). A gap leg along a mapped way names it, online and offline: Gap 106 m · along a path · may be closed to motor vehicles · ride on sight (the warning for a footpath with no motor tag, or a way tagged closed; a track or a cycle path is only named). A dead end with an end no chain of gaps reaches is not in the file: one your lifts open that way waits for a connection. Gaps other riders shared with you count as your lifts offline too, with the sharer's name on the gap leg (from the app after 16 October 2026): the phone keeps them from its last sync, hiding one or turning Use gaps shared with me off applies at once, and a gap the sharer stopped sharing drops at the next sync. Offline the card says the passage is in a group and how much dirt the group holds, from the map's own data; the passages, the gaps and the whole length need a connection.
- Tag a gap you think is a real track (join candidates, from the app after 15 October 2026). Under each gap of a card, Tag this gap opens a short form: the kind of way (track unless motor vehicles may not use it), the surface (required), and optionally the track grade, who can ride it, access from a sign you saw, the width and a note. It works offline too, also from a gap line you tap on the map when the card has no gap details: the tag waits on your phone (saved on this phone, sent when you are online) and goes out by itself when the network is back. It stays yours, private. Route to the gap plans the way to its dead end. After a ride whose recorded track passes within 25 m of both ends, the ride's page lists it under Gaps you explored. Then I rode it, it exists confirms it in one tap, which also lifts the gap's warning for you, and Share for OpenStreetMap or Copy the note hands over the OSM note text and a GeoJSON of the line, never a drawn way. You can add one photo. The card says how many riders tagged the gap: a cue, not a confirmation. Your tagged gaps are in the Library under the signal chip, with their stage.
- Share a gap you confirmed (the server has it from its image after 15 October 2026; the buttons come with the rider app's next build). A gap you rode and confirmed is yours to share: with chosen friends, all your friends, your groups, or every Epona rider. A one-tap I crossed it, it is safe stays yours alone. A gap shared with you opens passages for your plans exactly as your own lift does, and the plan names it: Gap 140 m, ride on sight · shared by Anna. A gap shared with every rider first shows 1 rider confirmed this gap, and routes for everyone once a second rider confirms it on their own ride (confirmed by 2 riders, no names). Use gaps shared with me (on by default, the same setting on the desktop) turns them all off, and Hide turns one off. When the sharer stops sharing or puts the warning back, it ends at your next sync; offline your phone keeps what it last synced, labelled the same way.
- Add to plan works offline: your phone orders the passages (in the order you added them, or Best order) with the same rules as the server, rides each one along its own line and routes the road between them around closed gates. The plan says "Planned on the phone, without a connection." A passage the offline routing engine will not ride is left out, with the reason.
- Plan a dirt track works offline too (from the app after 17 October 2026 and the passages files of 17 October 2026 on): with no connection, on the Offline engine, or when the server does not answer, your phone joins the passages you picked into the longest ride that never rides a stretch twice, with the server's own rules and answer — the gaps up to your limit (unchecked ones ride on sight, the risk accepted once per track), the paved links up to your limit from the phone's own road distances, what it leaves out and why, Add as out-and-back, Route me there from where you are and Swap ends. Move your gap limit or your paved-link limit and the track says so, with Plan again (from the app after 25 October 2026): with no connection your phone solves the track again with the new limits, keeping the same picks, out-and-backs and end. A passage the file does not hold (closed, behind a closed gate, or a dead end no chain of gaps reaches) is listed as not in your offline maps. With an older passages file, or without the part, the app asks you to download it or connect.
- A dirt plan, online or offline, ends at its last passage unless you set a destination since you opened the app; then it ends there, shown above the plan as Ends at and the place with × to drop it. A destination still in the form from an earlier session fills the ordinary A → B as before; adding the first passage clears it from the form, and it never ends a dirt plan. Removing the last passage clears the plan and plans nothing in its place. Offline, a destination outside your downloaded maps is said as such, with the country to download.
- Hide passages wet now uses the last radar answer; when it is more than 12 hours old the switch greys out and hides nothing.
- The pack sheet flags an update when the monthly rebuild changed the data.
Offline query behaviour
| Query | Online | Offline (tiles present) | Offline (no tiles) |
|---|---|---|---|
| Curvy-road search | Server DB query | Local SQLite query | No results |
| POI search | Server PostGIS | Local SQLite query | No results |
| Route planning | Valhalla server | The phone's own engine (the installed routing packs) | Cached last route only |
| Elevation chart | /grass/elevation/sample API | Not available (needs server) | Not available |
| Map tiles | MapLibre online | Online only | Blank map |
Offline, the phone's engine follows the server's rules for a place no road reaches: a destination on a track that joins nothing is asked again for the nearest road that connects, a point may move at most 15 km, and the vehicle you picked stays when no road gets there (the planner says why, by point, and can offer the nearest road instead; see the route planner in the mobile app guide).
Elevation profile charts (route and inline road chart) always require a server connection because they call the real-time /grass/elevation/sample endpoint.