Open source MIT licensed · macOS and Linux

Build your own
offline maps.

Cairn turns OpenStreetMap into everything a map app needs to work without a connection: vector basemap, hiking and cycling routes, terrain and a routing package. For any area Geofabrik publishes. One desktop app, one command line, one Rust pipeline.

Or from a terminal: cairn basemap --area rhone-alpes · Needs Java 21+ for the planetiler steps, and the app can fetch a JRE for you.

The Cairn desktop app showing the rhone-alpes area: hiking and cycling route overlays and basemap on top of hillshaded terrain, with a layer list on the left.

What it builds

Four files. A complete offline map.

Pick an area, and Cairn produces the archives a map app needs: tiles for drawing, routes for hiking and cycling, elevation for relief and 3D, and a graph for turn-by-turn routing.

<area>.mbtiles

Vector basemap

OpenMapTiles-schema vector tiles from z0 to z14: roads, water, landcover, buildings, places and POIs.

MVT · z0–14
<area>_routes.mbtiles

Hiking and cycling routes

Route relations in their own archive, so they ship and update separately, and come out a fraction of the basemap's size.

MVT · route layer
<area>_terrain.mbtiles

Terrain-RGB elevation

Elevation packed into tile pixels, for shaded relief and 3D terrain in any renderer that reads terrain-RGB.

terrain-RGB
<area>.vtiles

Valhalla routing package

The routing graph for the area, with elevation baked in, packed into a single file you can ship to a phone.

Valhalla · elevation included

Ordinary formats, no lock-in. Outputs are plain MBTiles, PMTiles and Valhalla, so they work with

tileserver-glQGISMapLibreand anything else that reads them

Pipeline

Ask for the end. Cairn builds the path.

Every step knows what it needs. Select only the package and its prerequisites run first, in order. Anything already built is skipped.

Select a step to see what Cairn runs for it:

Download OSMcairn download Elevation tilescairn elevation · .hgt Basemap<area>.mbtiles Routes<area>_routes.mbtiles Valhalla tilescairn valhalla-tiles Terrain RGB<area>_terrain.mbtiles Bathymaplow zooms · no inputs Valhalla package<area>.vtiles
  1. Download OSMcairn downloadneeds nothing
  2. Elevation tilescairn elevationneeds nothing
  3. Basemap<area>.mbtilesneeds Download OSM
  4. Routes<area>_routes.mbtilesneeds Download OSM
  5. Bathymapglobal low zoomsneeds nothing, built once for every area
  6. Terrain RGB<area>_terrain.mbtilesneeds Elevation tiles
  7. Valhalla tilescairn valhalla-tilesneeds Download OSM and Elevation tiles
  8. Valhalla package<area>.vtilesneeds Valhalla tiles

Selecting Valhalla package runs 4 steps, in order: Download OSM → Elevation tiles → Valhalla tiles → Valhalla package

Features

One pipeline, two front ends.

Use the desktop app when you want to see what's happening, the command line when you want to script it. Both run exactly the same code.

Desktop app

Pick an area. Tick the steps. Watch it build.

The Tauri app is a front end to the pipeline. Choose any Geofabrik area, tick the outputs you want, and Cairn plans the rest.

  • Live progress for every step
  • Cancel really cancels: the running process is stopped, not just hidden
  • Skips what's already built. A step counts as built when its files are present and not empty
  • Browse what an area produced: size, zooms and layers for every file
The Output tab of Cairn listing the files built for the rhone-alpes area, grouped into basemap and routes, with format, zoom range, size and layers for each file.
Command line

The same pipeline, from your terminal.

cairn runs the same steps with the same defaults as the app. Start a build in one, finish it in the other.

  • cairn options basemap documents every flag, with what it costs
  • An untouched run reproduces the reference pipeline's output bytes, and tests keep the documented defaults honest
  • The app's Docs tab reads from the binary itself, so it cannot drift
The Docs tab of Cairn explaining the build state and listing the eight steps: Download OSM, Elevation tiles, Basemap, Routes, Bathymap, Terrain RGB, Valhalla tiles and Valhalla package.
Presets

Measured, not guessed.

Each planetiler step ships two presets: measured, the default, and stock, planetiler's own defaults kept as a comparison baseline. Override anything with -o key=value.

Every flag was measured on a real rhone-alpes build, and cairn options tells you what each one buys and what it costs.

measured

default · --preset measured

  • max_point_buffer=4caps point-layer buffers
  • landcover_merge_maxzoom−19% of the z14 landcover layer
  • transportation_surface_detailroad surface and tracktype, +0.84%
  • drop_redundant_name_int−0.88%
  • water_pool_tolerance=1simpler swimming pools
  • poi_custom_ranksPOIs ordered for an outdoor map

stock

--preset stock

  • planetiler's own defaults
  • nothing tuned
  • the baseline the measured preset is compared against
Try one flag at a time: cairn basemap --area $AREA -o transportation_surface_detail=false
Map view

Inspect everything you just built.

A built-in map reads the generated archives straight from disk. Layer them, flip between hillshade, raster and 3D terrain, and route live against the package you just made.

  • Inspect
  • Route
  • Profile
  • Tiles
  • Style
  • Compare two layers side by side with a swipe
  • Hillshade, raster or 3D terrain, drawn from the terrain-RGB tiles
  • In-app live routing against the generated Valhalla package
The Cairn map view zoomed in on part of the rhone-alpes area: basemap, routes and landcover drawn over a hillshade made from the terrain tiles. The same area tilted in 3D terrain mode, with the basemap and routes draped over the relief. The whole rhone-alpes area at low zoom with route and boundary overlays on hillshade.

And under the hood

Native Rust ports

A terrain-RGB renderer with no GDAL or PROJ, a Valhalla packager, and in-process routing through the Valhalla library. No prime_server, no zmq.

Bring your own area

Any area Geofabrik publishes, by its id: rhone-alpes, france. Steps clip to the area's own boundary, or pass --poly-shape to clip to your own.

Resumable by design

cairn state --area $AREA reports which outputs exist. Delete a file, or clear a step, and only the step that makes it runs again.

Shared where it should be

Elevation tiles and the Valhalla graph are shared between areas. Build the graph once for a parent area and routes don't stop at a border.

Measured

Smaller files. Same answers.

Numbers from real builds of rhone-alpes, compared against planetiler and the reference scripts.

−11.7%

Basemap size

The measured preset shrinks the rhone-alpes basemap by 11.7% compared with planetiler's defaults.

−19.4%

Routes archive

The same preset shrinks the rhone-alpes routes archive by 19.4% against planetiler's defaults.

−2.8%

Valhalla package

From identical input, the Rust packager produced 212.9 MiB where the reference script produced 219.0 MiB.

0.0 m

Terrain, mean deviation

At z13 the terrain renderer matches the reference archive: mean |Δ| 0.0 m, worst case 1 m, which is one quantisation step.

0.08 s

A 59.2 km route

In-process routing from Grenoble to Chambéry, no server involved. Routed in 0.08 s.

All figures measured on a rhone-alpes build.

Command line

One binary. Every step.

Everything the app does is a cairn subcommand. Run them in order, or run only the last one and let the dependencies fill in.

~/maps
# one area, start to finish$ export AREA=rhone-alpes$ cairn download --area $AREA        # OSM extract from Geofabrik$ cairn basemap --area $AREA         # vector basemap$ cairn routes --area $AREA          # route relations$ cairn elevation --area $AREA       # .hgt tiles$ cairn terrain --area $AREA         # terrain-RGB$ cairn valhalla-tiles --area $AREA  # routing graph$ cairn package --area $AREA         # Valhalla package # what's built, and what every flag costs$ cairn state --area $AREA$ cairn options basemap --presets$ cairn basemap --area $AREA -o transportation_surface_detail=false

Everything documents itself.

  • cairn options <step> lists every flag with what it costs. --presets adds the option sets that ship.
  • cairn state --area $AREA shows which outputs exist, and … clear <step> removes one.
  • Every step clips to the area's own boundary, fetching the .poly from Geofabrik the first time it needs it.
  • cairn catalog lists the areas you've generated and their files. cairn route routes between points using a package, and cairn profile samples an elevation profile along a line.

Download

Free, and yours to keep.

Grab the app, or just the command line. Every download lives on the latest GitHub release.

Recommended for you

Linux

The desktop app as a portable AppImage or a native package.

.AppImage.deb.rpm
Download for Linux

CLI only

The standalone cairn command line, for servers and scripts. No app needed.

cairn-<version>-<target>.tar.gz
Download the CLI

Builds target macOS and Linux today. Windows has not been released.

Before you build

  • Java 21+ is needed for the planetiler steps. The app can download a JRE on first run.
  • The planetiler jar is fetched on first use.
  • OSM extracts, elevation tiles and the Valhalla graph are downloaded per area. They are never bundled.

Or build from source

$ git clone --recurse-submodules https://github.com/Akylas/cairn$ cd cairn$ npm install && npm run tauri dev

FAQ

Straight answers.

What's the licence of the data?

Cairn itself is MIT licensed. The map data it processes is OpenStreetMap, available under the Open Database Licence (ODbL), which requires attribution. If you publish tiles built with Cairn, credit © OpenStreetMap contributors.

Elevation and other sources you configure have their own terms, so check those for the ones you use.

Does it need internet?

To build, yes, for the downloads: the OSM extract, elevation tiles, the planetiler jar and the Valhalla graph are fetched per area. Once the outputs exist they are plain files, and a map app can use them with no connection at all.

How big are the builds?

It depends on the area and on your options. For reference, the rhone-alpes basemap is about 250 MB. cairn options lists what each flag costs, so you can trade detail for size.

How is this different from running planetiler directly?

Planetiler still builds the vector tiles. Cairn wraps it with tuned, measured presets, and covers the rest of the job: elevation, terrain-RGB and the Valhalla routing package. It plans the steps from their dependencies, clips each to the area's boundary, remembers what's built, and gives you a desktop app with live progress and a map to inspect the result.

Does it run on Windows?

Not yet. The CI builds the app and CLI for macOS and for Linux (Ubuntu 22.04 as the baseline). Windows is left out on purpose: Valhalla's support for it is poor and this pipeline has never been run there. Windows is not released.

Who makes Cairn?

It was born as the build tool behind AlpiMaps, and grew into a tool for anyone who wants their own offline map data. It is open source, and contributions are welcome on GitHub.