// This skill generates interactive maps using the Leaflet JavaScript library. Use this skill when users need to create geographic visualizations, location-based data displays, or interactive maps for educational textbooks. The skill creates complete MicroSim packages with HTML, CSS, and documentation, optimized for iframe embedding in narrow MkDocs pages with navbar and TOC.
| name | map-generator |
| description | This skill generates interactive maps using the Leaflet JavaScript library. Use this skill when users need to create geographic visualizations, location-based data displays, or interactive maps for educational textbooks. The skill creates complete MicroSim packages with HTML, CSS, and documentation, optimized for iframe embedding in narrow MkDocs pages with navbar and TOC. |
This skill creates interactive Leaflet maps as MicroSims for intelligent textbooks built with MkDocs Material theme.
Use this skill when users request:
Ask the user for the following information:
Example user input: "Create a map showing major universities in California with markers for each campus"
Create the MicroSim directory:
docs/sims/[map-name]/
Naming convention: Use kebab-case (e.g., california-universities, ancient-rome-map, world-capitals)
If the map includes markers or GeoJSON data, create a map-data.json file:
{
"center": {
"lat": 37.7749,
"lng": -122.4194
},
"zoom": 10,
"title": "Map Title",
"subtitle": "Map Subtitle",
"markers": [
{
"lat": 37.7749,
"lng": -122.4194,
"title": "Location Name",
"description": "Location description",
"category": "category-name"
}
]
}
For borders/regions: Use GeoJSON format for complex geometries.
Create main.html using the template from assets/template-iframe-main.html:
Key elements:
Replace placeholders:
{{TITLE}} - Map title{{SUBTITLE}} - Map subtitle{{MAP_HEIGHT}} - Map container height (default: 400px)Create style.css using the template from assets/template-iframe-style.css:
Critical requirements for iframe embedding:
body { margin: 0; padding: 0; } - No body marginsCustomization options:
Create script.js using the template from assets/template-script.js:
Core functionality:
Replace placeholders:
{{CENTER_LAT}}, {{CENTER_LNG}} - Map center coordinates{{ZOOM}} - Initial zoom level{{MARKERS}} - Marker data array{{TILE_LAYER}} - Tile layer URL (OpenStreetMap, satellite, etc.)Common tile layers:
https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.pnghttps://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}https://{s}.tile.opentopomap.org/{z}/{x}/{y}.pngCreate index.md using the template from assets/template-index.md:
Structure:
iframe embed format:
<iframe src="main.html" width="100%" height="700" frameborder="0"></iframe>
[View Fullscreen](main.html){:target="_blank"}
Create metadata.json using the template from assets/template-metadata.json:
Dublin Core fields:
Map-specific fields:
map_type: "interactive", "choropleth", "route", etc.center_lat, center_lng: Center coordinateszoom_level: Initial zoom levelmarker_count: Number of markersconcepts: Array of related conceptsbloom_taxonomy: Cognitive level (Remember, Understand, Apply, etc.)Add the new map to the navigation in mkdocs.yml:
nav:
- MicroSims:
- Introduction: sims/index.md
- [Map Name]: sims/[map-name]/index.md
Naming: Use Title Case for navigation labels
Perform these validation steps:
Direct HTML test: Open docs/sims/[map-name]/main.html in browser
MkDocs test: Run mkdocs serve and navigate to the map page
Browser compatibility: Test in Chrome, Firefox, Safari
Mobile test: Verify responsive behavior on mobile devices
Basic map with multiple markers:
const markers = [
{ lat: 40.7128, lng: -74.0060, title: "New York", description: "The Big Apple" },
{ lat: 34.0522, lng: -118.2437, title: "Los Angeles", description: "City of Angels" }
];
markers.forEach(marker => {
L.marker([marker.lat, marker.lng])
.bindPopup(`<b>${marker.title}</b><br>${marker.description}`)
.addTo(map);
});
Show a highlighted border or region:
const region = {
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[...]]
}
};
L.geoJSON(region, {
style: { color: 'red', weight: 3, fillOpacity: 0.2 }
}).addTo(map);
Toggle between map types:
const street = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png');
const satellite = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}');
const baseMaps = {
"Street": street,
"Satellite": satellite
};
L.control.layers(baseMaps).addTo(map);
street.addTo(map); // Default layer
Use custom icons for different categories:
const universityIcon = L.icon({
iconUrl: 'university-icon.png',
iconSize: [32, 32],
iconAnchor: [16, 32],
popupAnchor: [0, -32]
});
L.marker([lat, lng], { icon: universityIcon }).addTo(map);
const markers = L.markerClusterGroup();
markers.addLayer(L.marker([lat, lng]));
map.addLayer(markers);
#map div has a fixed height in CSSbody { margin: 0; padding: 0; } in CSS