marimo/skills/maputnik-layer/SKILL.md
Maputnik — visual editor for MapLibre GL vector-tile styles. Pure-JS SPA built from upstream source via npm at image build time, served as static dist by python -m http.server. Pairs with osm-data's martin tile server. Use when working with the maputnik layer, the Vite --base=/ build override (critical fix; default --base=/maputnik/ produces 404 asset paths), or the asset-base lock-in eval test.
npx skillsauth add overthinkos/overthink-plugins maputnik-layerInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Maputnik is a pure-JS SPA for visually editing MapLibre GL JS style
JSON files. Built from upstream source (felt/maputnik) via npm at
image build time, served as a static dist by Python's stdlib
http.server. Composed by /ov-marimo:marimo-ml so operators can
iterate on the streets-map style against the in-pod martin tile
server (/ov-marimo:osm-data-layer).
| Property | Value |
|----------|-------|
| Dependencies | supervisord |
| Distros | fedora (sole; needs node + npm + git for build) |
| Build deps | nodejs, npm, git |
| Ports | 8000 (host-mapped to 28000) |
| Service | maputnik (supervisord, restart: always) |
| Static dist | /opt/maputnik/build/ (Vite dist/ renamed) |
service:
- name: maputnik
exec: /usr/bin/python3 -m http.server 8000 --directory /opt/maputnik/build
restart: always
working_directory: /opt/maputnik
Pure stdlib server — no marimo-pixi-env coupling. The system
python3 from supervisord's own RPM dep handles the static serve.
Maputnik's package.json defines "build": "tsc && vite build".
Vite's default base path for builds is --base=/maputnik/. That
default bakes /maputnik/assets/* URL references into the emitted
index.html — but we serve the dist at root (/) via
python -m http.server, so all those baked URLs 404 in the
browser.
Symptom (before fix): the maputnik UI loads at
http://127.0.0.1:28000/ showing a blank page; browser dev-tools
shows asset 404s for /maputnik/assets/index-*.js etc.
Fix in the build cmd:
- cmd: |
set -euo pipefail
git clone --depth 1 https://github.com/maplibre/maputnik /tmp/maputnik
cd /tmp/maputnik
npm ci --no-audit --no-fund
# Override Vite's default --base=/maputnik/ so asset URLs are
# root-relative and resolve against our serve path. The `--`
# forwards the flag through npm to vite.
npm run build -- --base=/
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 /root/.npm
user: root
A deploy-scope eval probe greps the served HTML for the (forbidden)
/maputnik/ prefix and fails if present. Locks in the fix against a
future revert to the Vite default:
- id: maputnik-asset-base-not-prefixed
scope: deploy
command: |
! curl -fsS http://localhost:8000/ | grep -q '"/maputnik/'
in_container: true
exit_status: 0
Plus the standard probes (also deploy-scope):
maputnik-running — supervisord program is RUNNINGmaputnik-port-reachable — TCP 8000 reachablemaputnik-http-up — GET / returns 200The streets-map style in /ov-marimo:notebook-osm cell 7 is a
small inline JSON. Operators iterating on richer styles can:
http://127.0.0.1:28000/http://127.0.0.1:23000/monacostyle: 'http://...' in the MapLibre constructor)/ov-marimo:marimo-ml — image composing this layer/ov-marimo:osm-data-layer — companion martin tile server/ov-marimo:notebook-osm — uses an inline style; maputnik can author richer ones/ov-infrastructure:supervisord — service runtimetools
Use when authoring or modifying a charly PLUGIN — a candy with a `plugin:` block that contributes Providers (verbs/kinds/deploy-targets/steps/builders/commands), its own CUE schema, builtin (compiled-in) or external (out-of-tree git repo). Covers the unified Provider model, the per-plugin CUE-schema contract (single source → Go params for dev + schema-over-Describe RPC for runtime), the SDK, and the loader.
tools
The CUE data-validation / configuration CLI (cue), pinned to v0.16.1. Use when working with the cue candy, installing the cue binary into a box or onto a target:local dev host, or running the offline schema-vendoring pipeline that feeds charly's egress validation.
tools
CUE EGRESS validation — validating (and, where it adds value, generating) the config files charly WRITES to a system BEFORE the bytes hit disk. MUST be invoked before working on charly/egress.go, the vendored schemas under candy/plugin-egress/egress-schemas/vendor/, the ValidateEgress / registerVendoredEgressKind path, the offline `task cue:vendor` pipeline, or adding an egress schema for any written artifact (cloud-init, k8s manifests, traefik routes, runtime config, install ledger, systemd/quadlet units, ssh_config, libvirt XML).
tools
Kubernetes cluster-probe declarative check verb — the `kube:` check verb (nodes, pods, ingress, storage class, addon health, apply/delete, and arbitrary resource GETs) served out-of-process by the candy/plugin-kube plugin (vendored client-go; no external kubectl required).