Install
openclaw skills install @stanestane/versatile-map-makeropenclaw skills install @stanestane/versatile-map-makerCreate real, editable SVG maps from either built-in public map data or user-supplied geometry.
Use the fastest honest path:
Always be explicit about precision: region boundaries are as exact as the source geometry; hand-entered lines are schematic; coarse datasets must not be described as fine-grained maps.
Install only what is needed for the chosen path:
python -m pip install numpy cairosvg
Optional:
npm for the Highcharts fast path.geopandas, shapely, or ogr2ogr only when converting shapefiles/TopoJSON outside the bundled scripts.matplotlib only if you extend palettes beyond the built-in script palettes.Use this for world, continent, country, state, or province maps when admin1 granularity is enough.
python scripts/fetch_base_map.py --list serbia
python scripts/fetch_base_map.py countries/rs/rs-all ./mapwork
python scripts/fit_transform.py ./mapwork/rs-all.svg ./mapwork/rs-all.geo.json ./mapwork/transform.json
Highcharts keys commonly look like:
custom/worldcustom/europecountries/us/us-allcountries/fr/fr-allcountries/rs/rs-allIf npm is missing or the key is unavailable, switch to Path B.
Use this for counties, municipalities, custom regions, historical maps, fictional regions, or any project where the built-in map is too coarse.
Input should be GeoJSON when possible. If the user has a shapefile, convert it to GeoJSON with GIS tooling first.
python scripts/geojson_to_svg.py regions.geojson base.svg \
--id-field GEOID --name-field NAME --metadata-out regions-index.json \
--transform-out transform.json
Then color the generated SVG just like a Highcharts map:
python scripts/recolor_choropleth.py base.svg data.json choropleth.svg \
--title "..." --subtitle "..." --legend-label "..."
The generated SVG path IDs come from --id-field; if omitted, the script tries common fields such as id, GEOID, ISO_A2, hc-key, hasc, and name.
For JSON data already keyed by region id, use it directly:
{"US.CA": 39.5, "US.TX": 30.0}
For CSV tables, create the JSON mapping:
python scripts/join_data.py data.csv data.json --id-col region_id --value-col value --numeric
If labels do not match geometry IDs, inspect regions-index.json or the GeoJSON properties and build a clean crosswalk. Do not guess ambiguous matches.
Numeric data uses a continuous color scale; text data uses categorical swatches.
python scripts/recolor_choropleth.py base.svg data.json out.svg \
--title "Population by Region" \
--subtitle "Source: ..." \
--legend-label "People" \
--cmap YlOrRd \
--missing-fill "#F2F2F2" \
--style style.json
Use a style JSON when the user needs brand colors or a different visual tone:
{
"font_family": "Arial, sans-serif",
"neutral_fill": "#F2F2F2",
"neutral_stroke": "#BDBDBD",
"qualitative": ["#4E79A7", "#F28E2B", "#59A14F"],
"title_fill": "#222222"
}
Use overlays for historical borders, custom territories, service areas, disputed/uncertain lines, routes, and highlighted regions.
Boundary JSON accepts either a single ring or a FeatureCollection-like object:
{
"features": [
{"type": "polygon", "coordinates": [[[20.4,44.8],[21.0,44.6],[20.4,44.8]]], "label": "Inside"},
{"type": "line", "coordinates": [[20.4,44.8],[21.0,44.6]], "dash": true, "label": "Approximate"},
{"type": "point", "coordinates": [20.46,44.81], "label": "Capital"}
]
}
Draw it:
python scripts/overlay_boundary.py base.svg transform.json boundary.json out.svg \
--title "Historical Boundary" \
--subtitle "Modern base, historical overlay" \
--legend-inside "Historical area" \
--legend-outside "Modern reference"
When a boundary follows a river/coast/administrative border, prefer real geometry. For rivers:
python scripts/fetch_rivers.py "Danube" "Sava" --out rivers.json
python scripts/fetch_rivers.py --slice rivers.json "Danube" 20.455,44.840 22.545,44.226 --out danube-segment.json
If a real feature cannot be found, draw a schematic line and label the uncertainty.
Render a PNG preview before delivery:
python - <<'PY'
import cairosvg
cairosvg.svg2png(url="out.svg", write_to="preview.png", output_width=1000)
PY
Inspect the preview for:
Return the final SVG and any useful preview PNG. Include a short note naming:
references/data-sources.mdreferences/geometry-inputs.mdreferences/styling.mdreferences/technique.md