maputnik
| Version | 2026.144.1443 |
| Repo | superproject |
Visual MapLibre GL style editor (Maputnik SPA) built from upstream source and served as a static dist over HTTP on port 8000
Clones the upstream maplibre/maputnik repo at image-build time, runs
npm ci + npm run build -- --base=/, and copies Vite’s emitted
dist/ to /opt/maputnik/build/. The –base=/ override keeps asset URLs
root-relative so they resolve under the serve path instead of 404ing
at /maputnik/assets/*. The stdlib python3 -m http.server 8000 --directory /opt/maputnik/build runs as the always-restart maputnik
service. It pairs with the osm-tools martin tile server (the editor at
:8000 points at the tile catalog at :3000). Every fact below is
observable: the built SPA dist + index.html, the node build
toolchain, the running service, the HTTP 200 the editor returns, and
the absence of the /maputnik/ asset prefix in the served HTML.
Services
Section titled “Services”maputnik
Acceptance plan
Section titled “Acceptance plan”This candy’s plan: — the runnable spec charly check executes against a live deployment. check: steps are idempotent probes; run: steps change state.
| Intent | Step |
|---|---|
run |
mkdir=/opt/maputnik |
run |
command=set -euo pipefail # Clone shallow + most recent tag’s tip. The maputnik repo has no # binary releases on GitHub — source build is the canonical install. git clone –depth 1 https://github.com/maplibre/maputnik /tmp/maputnik cd /tmp/maputnik # npm ci over npm install because lockfile is upstream-provided # and we want deterministic resolution. –no-audit + –no-fund cut # ~5 sec of network chatter that only spams stderr. npm ci –no-audit –no-fund # Maputnik’s package.json "build": "tsc && vite build" runs # vite with its default --base=/maputnik/, which bakes # /maputnik/assets/* references into the emitted HTML. We # serve the static dist at / via python -m http.server, so # those baked paths 404 in the browser. Override base to / # so asset URLs are root-relative and resolve against our # serve path. The -- forwards the flag through npm to vite. npm run build – –base=/ # Maputnik uses Vite (tsc && vite build --mode=production); Vite # default output is dist/, NOT build/ (the source-tree build/ # is just release scripts). Copy the actual SPA artifact and # error loudly if the layout changes upstream. if [ -d dist ]; then mkdir -p /opt/maputnik cp -r dist /opt/maputnik/build else echo “maputnik build did not produce ./dist directory” >&2 ls -la exit 1 fi cd / rm -rf /tmp/maputnik # Drop npm cache to shrink image (~150-300 MB delta). rm -rf /root/.npm |
check |
the maputnik static dist directory was built from upstream source |
check |
the SPA entrypoint index.html is present in the served dist |
check |
the node runtime used to build the SPA is installed and runnable |
check |
the maputnik service is running under the init system |
check |
the static SPA answers HTTP 200 at the container root on the published port |
check |
the served HTML carries no /maputnik/ asset prefix, so asset URLs resolve at the serve root |
agent-check |
the loaded SPA presents the Maputnik visual style editor interface (layer list and map canvas), not a blank page |
check |
addr=127.0.0.1:${HOST_PORT:8000} |