Visualizes pre-ordered routes and location maps via scripts/map_generator.py.
Fully offline Python engine — no outbound HTTP from Python. Road geometry
rendered directly when provided by a connector; OSRM used browser-side as a
fallback when it is not.
Steps
1. Choose kind
| Value |
Use when |
"map" |
Plot locations only — no path (weather, CRM records, site lists) |
"route" |
Ordered stops + path |
"auto" |
Default — infers map unless stops key or round_trip hint |
2. Resolve coordinates — per point, in order:
lat/lon already present — from user, connector result, Dataverse, CRM, CSV, etc. Never overwrite.
- Alias match in
assets/place_lookup.json
- Web-search the place's lat/lon, then add to payload
Never call external geocoding APIs from the script. Never invent coordinates.
3. Pass connector route data (when available)
If an upstream connector (Azure Maps, Bing Maps, etc.) returned routing data,
pass it directly — the visualizer will use it for accurate distances and the
actual road polyline in PNG and HTML:
| Field |
Source |
Effect |
route_geometry |
Connector road polyline |
Draw actual road path in PNG + HTML |
legs |
Connector leg breakdown |
Show per-leg distance/time table |
route_source |
e.g. "azure_maps" |
Attribution badge on map and outputs |
total_distance_m |
Connector total distance |
Accurate distance in header + exports |
total_duration_s |
Connector total time |
Accurate time in header + exports |
Without these, the PNG uses straight lines (labeled schematic) and the
HTML calls OSRM browser-side for road routing.
4. Point fields
| Field |
Notes |
lat, lon |
Required (or place_lookup match) |
name |
Display label |
value |
Metric — "24 C", "$1.2M", CRM field, etc. |
icon |
See icon list below |
color |
Hex (validated — invalid values fall back to default) |
order |
Optional sequence number (connector-assigned) |
5. Call generate()
import sys; sys.path.insert(0, "scripts")
from map_generator import generate
# Minimal — stops in provided order, schematic PNG, OSRM HTML
result = generate({
"kind": "route",
"title": "Delivery run",
"stops": [
{"name": "Depot", "lat": -33.86, "lon": 151.21},
{"name": "Stop A", "lat": -33.90, "lon": 151.18},
{"name": "Stop B", "lat": -33.88, "lon": 151.15},
],
# Optional exports (all off by default):
# "html": True "csv": True "geojson": True "kml": True
# "map_links": True "qr_codes": True
})
# With connector road data — produces accurate PNG + no OSRM needed
result = generate({
"kind": "route",
"title": "Delivery run — Azure Maps",
"stops": [...],
"route_geometry": [ # connector road polyline
{"lat": -33.860, "lon": 151.210},
{"lat": -33.865, "lon": 151.208},
...
],
"legs": [ # per-leg breakdown
{"from": "Depot", "to": "Stop A", "distance_m": 5200,
"duration_s": 420, "summary": "via Parramatta Rd"},
{"from": "Stop A", "to": "Stop B", "distance_m": 3100,
"duration_s": 280, "summary": "via Church St"},
],
"route_source": "azure_maps",
"total_distance_m": 8300,
"total_duration_s": 700,
"html": True,
})
print(result["markdown"])
Key result keys: chart_path (PNG, always), html_path, csv_path,
geojson_path, kml_path, map_links_path, qr_sheet_path,
google_maps_url, apple_maps_url, bing_maps_url, has_road_geometry,
route_source, generated_exports.
6. Reply — paste result["markdown"]. It always ends with an Optional
exports hint. Clarify:
- PNG = road route when
route_geometry provided, else straight-line schematic
- HTML = connector polyline embedded (no OSRM) when geometry provided, else OSRM browser-side
schematic_order: true — opt-in offline stop ordering (NN + 2-opt, straight-line estimate); always prefer a connector for real road order
Icons
pin sunny partly-cloudy cloudy rain storm snow fog wind
hot cold office home factory hospital school warning check
star shop truck
Guardrails
- Never overwrite
lat/lon from user or prior tools.
- Never call external geocoding/routing APIs from the Python script.
- Never invent coordinates — ask the user or web-search.
- Never reorder stops unless
"schematic_order": true is explicitly set.
Bundled files
scripts/map_generator.py — engine (generate)
assets/place_lookup.json — place aliases
references/cheatsheet.md — full payload reference + CLI flags
1---2name: route-map-visualizer3description: Use this skill to visualize routes and locations on a map — especially after an upstream tool call (routing connector, Azure Maps, Bing Maps connector, HERE, Mapbox, Dataverse, CRM, SharePoint, or any connector that returns coordinates) has returned ordered stops, coordinates, distances, or road geometry. Produces PNG, interactive HTML, GeoJSON, KML, deep links, and QR codes. Also use for marker maps (weather, CRM data, site lists) and for any request to "show these on a map", "map these locations", or "visualize this route". DO NOT use this skill to compute routing — call a routing connector first, then pass the result here for visualization.4---56Visualizes pre-ordered routes and location maps via `scripts/map_generator.py`.7Fully offline Python engine — no outbound HTTP from Python. Road geometry8rendered directly when provided by a connector; OSRM used browser-side as a9fallback when it is not.1011## Steps1213**1. Choose kind**1415| Value | Use when |16| --- | --- |17| `"map"` | Plot locations only — no path (weather, CRM records, site lists) |18| `"route"` | Ordered stops + path |19| `"auto"` | Default — infers `map` unless `stops` key or `round_trip` hint |2021**2. Resolve coordinates** — per point, in order:221. `lat`/`lon` already present — from user, connector result, Dataverse, CRM, CSV, etc. **Never overwrite.**232. Alias match in `assets/place_lookup.json`243. Web-search the place's lat/lon, then add to payload2526Never call external geocoding APIs from the script. Never invent coordinates.2728**3. Pass connector route data (when available)**2930If an upstream connector (Azure Maps, Bing Maps, etc.) returned routing data,31pass it directly — the visualizer will use it for accurate distances and the32actual road polyline in PNG and HTML:3334| Field | Source | Effect |35| --- | --- | --- |36| `route_geometry` | Connector road polyline | Draw actual road path in PNG + HTML |37| `legs` | Connector leg breakdown | Show per-leg distance/time table |38| `route_source` | e.g. `"azure_maps"` | Attribution badge on map and outputs |39| `total_distance_m` | Connector total distance | Accurate distance in header + exports |40| `total_duration_s` | Connector total time | Accurate time in header + exports |4142Without these, the PNG uses straight lines (labeled **schematic**) and the43HTML calls OSRM browser-side for road routing.4445**4. Point fields**4647| Field | Notes |48| --- | --- |49| `lat`, `lon` | Required (or place_lookup match) |50| `name` | Display label |51| `value` | Metric — `"24 C"`, `"$1.2M"`, CRM field, etc. |52| `icon` | See icon list below |53| `color` | Hex (validated — invalid values fall back to default) |54| `order` | Optional sequence number (connector-assigned) |5556**5. Call generate()**5758```python59import sys; sys.path.insert(0, "scripts")60from map_generator import generate6162# Minimal — stops in provided order, schematic PNG, OSRM HTML63result = generate({64 "kind": "route",65 "title": "Delivery run",66 "stops": [67 {"name": "Depot", "lat": -33.86, "lon": 151.21},68 {"name": "Stop A", "lat": -33.90, "lon": 151.18},69 {"name": "Stop B", "lat": -33.88, "lon": 151.15},70 ],71 # Optional exports (all off by default):72 # "html": True "csv": True "geojson": True "kml": True73 # "map_links": True "qr_codes": True74})7576# With connector road data — produces accurate PNG + no OSRM needed77result = generate({78 "kind": "route",79 "title": "Delivery run — Azure Maps",80 "stops": [...],81 "route_geometry": [ # connector road polyline82 {"lat": -33.860, "lon": 151.210},83 {"lat": -33.865, "lon": 151.208},84 ...85 ],86 "legs": [ # per-leg breakdown87 {"from": "Depot", "to": "Stop A", "distance_m": 5200,88 "duration_s": 420, "summary": "via Parramatta Rd"},89 {"from": "Stop A", "to": "Stop B", "distance_m": 3100,90 "duration_s": 280, "summary": "via Church St"},91 ],92 "route_source": "azure_maps",93 "total_distance_m": 8300,94 "total_duration_s": 700,95 "html": True,96})97print(result["markdown"])98```99100Key result keys: `chart_path` (PNG, always), `html_path`, `csv_path`,101`geojson_path`, `kml_path`, `map_links_path`, `qr_sheet_path`,102`google_maps_url`, `apple_maps_url`, `bing_maps_url`, `has_road_geometry`,103`route_source`, `generated_exports`.104105**6. Reply** — paste `result["markdown"]`. It always ends with an **Optional106exports** hint. Clarify:107- **PNG** = road route when `route_geometry` provided, else straight-line schematic108- **HTML** = connector polyline embedded (no OSRM) when geometry provided, else OSRM browser-side109- **`schematic_order: true`** — opt-in offline stop ordering (NN + 2-opt, straight-line estimate); always prefer a connector for real road order110111## Icons112113`pin` `sunny` `partly-cloudy` `cloudy` `rain` `storm` `snow` `fog` `wind`114`hot` `cold` `office` `home` `factory` `hospital` `school` `warning` `check`115`star` `shop` `truck`116117## Guardrails118119- Never overwrite `lat`/`lon` from user or prior tools.120- Never call external geocoding/routing APIs from the Python script.121- Never invent coordinates — ask the user or web-search.122- Never reorder stops unless `"schematic_order": true` is explicitly set.123124## Bundled files125126- `scripts/map_generator.py` — engine (`generate`)127- `assets/place_lookup.json` — place aliases128- `references/cheatsheet.md` — full payload reference + CLI flags