Documentation
OpenRoadCode Map Builder
Source:
tools/map_builder/README.md
Reproducible Debian-container workflow for generating the offline map and routing data consumed by OpenRoadCode.
It automates the previously manual chain: discover Geofabrik regions, download and validate OSM PBF extracts, merge selected regions when necessary, build MapLibre-compatible MBTiles with tilemaker, install the OpenRoadCode map style and offline glyphs, build Valhalla routing data, validate all generated artifacts, write a build manifest, and publish/deploy the result as a /srv/openroadcode dataset.
The recommended production model uses a dedicated map-build machine. The vehicle does not compile its own map data; it pulls validated datasets from the build machine with scripts/runtime/pull_navigation_data.sh. See Navigation Build and Deployment.
Toolchain
The toolchain is pinned in toolchain.lock to specific tilemaker, Valhalla, glyph, and Debian versions. A container engine is used only as a build/data-compilation environment; the OpenRoadCode runtime does not require one. The scripts use Docker by default. To use Podman, set CONTAINER_ENGINE=podman:
CONTAINER_ENGINE=podman ./scripts/build-image.sh
CONTAINER_ENGINE=podman ./scripts/run-builder.sh tui
Build image
cd tools/map_builder
./scripts/build-image.sh
Interactive region selector
./scripts/run-builder.sh tui
The runner bind-mounts the local builder/ and templates/ directories into the container, so Python, TUI, and style-template edits are available immediately. Rebuild the image only after changing the Dockerfile, toolchain versions, or container-installed dependencies.
Controls: Up/Down and PageUp/PageDown navigate, Right expands or collapses a region group, Left collapses or moves to its parent, Space selects, / searches, c clears the search, Enter accepts the selected regions, and q quits. b also accepts the selection. Parent/child region combinations are rejected to prevent duplicate map data.
The last accepted selection is stored in .cache/selected-regions.json. On the next run, regions that still exist in the current Geofabrik index are selected with [x], and their parent groups are expanded so they are visible. Quitting with q leaves the previous accepted selection unchanged.
Non-interactive build
./scripts/run-builder.sh build --regions north-america/us/michigan
Multiple regions are comma separated:
./scripts/run-builder.sh build --regions north-america/us/michigan,north-america/us/ohio
After a successful interactive or non-interactive build, the builder reports the selected region names, their combined source PBF size, total deployable output size, elapsed build time, and output path.
List known Geofabrik IDs with:
./scripts/run-builder.sh list
Generated output
The host build-output/ directory is mounted in the container as /srv/openroadcode, so generated file URLs and Valhalla paths are identical during validation and after deployment.
build-output/
├── build-manifest.json
├── maps/
│ ├── source/
│ ├── vector/openroadcode.mbtiles
│ ├── glyphs/
│ ├── styles/openroadcode.json
│ └── routes/
└── valhalla/
├── valhalla.json
├── admins.sqlite
├── timezones.sqlite
├── tiles/
└── tiles.tar
maps/routes/ is runtime/debug space. Routes are sent dynamically to the native map renderer rather than generated as part of the base dataset. Vehicle-side deployment preserves this directory across dataset updates.
The canonical style name is openroadcode.json; runtime code should not depend on a region-specific filename.
Validation
Validation runs automatically after a build. It checks source PBFs with osmium, MBTiles SQLite integrity and required vector layers, style JSON and runtime sources, glyph presence, Valhalla databases/tiles/extract, an optional valhalla_service /status smoke test, and SHA-256 checksums for key artifacts.
Run validation again with:
./scripts/validate-host.sh
A dataset is not considered deployable without a validated build-manifest.json.
Publish on the map-build machine
The recommended vehicle-pull model publishes the latest validated dataset at /srv/openroadcode on the map-build machine:
./scripts/deploy-to-srv.sh
The deployment script refuses to install an output tree without a validated build-manifest.json. It synchronizes generated data into /srv/openroadcode while preserving maps/routes/ as runtime/debug space.
The vehicle can then preview and pull that dataset over SSH:
./scripts/runtime/pull_navigation_data.sh \
--source mapbuilder@MAP_HOST:/srv/openroadcode \
--dry-run
./scripts/runtime/pull_navigation_data.sh \
--source mapbuilder@MAP_HOST:/srv/openroadcode
These commands are run from the OpenRoadCode repository on the vehicle, not from tools/map_builder on the build host.
SSH key authentication is recommended. For the pull model, the vehicle only requires read access to the published build-machine dataset; the build machine does not need privileged SSH access to the vehicle.
Optional push deployment
deploy-to-srv.sh --remote remains available for development or manually managed targets:
./scripts/deploy-to-srv.sh --remote openroad@192.168.1.50
make deploy REMOTE=openroad@192.168.1.50
For production vehicle updates, prefer the Pi-initiated pull workflow because it controls update timing, stages and validates the incoming dataset, retains the previous dataset, and can roll back after a failed Valhalla restart.
Cache and scratch data
.cache/ stores downloaded Geofabrik data, .scratch/ stores intermediate build data, and build-output/ contains only the deployable result. These directories are intentionally ignored by Git.
Tests
make test
The included tests cover Geofabrik region parsing/selection rules and MapLibre style installation/validation.
Attribution
Generated datasets are based on OpenStreetMap/Geofabrik data and use open-source tilemaker, Valhalla, and glyph assets. Downstream applications must preserve the applicable licenses and attribution requirements.