with one click
preview-leaflet
// Create interactive maps with markers, routes, and geographic data using Leaflet
// Create interactive maps with markers, routes, and geographic data using Leaflet
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | preview-leaflet |
| description | Create interactive maps with markers, routes, and geographic data using Leaflet |
| user-invocable | true |
| commands | ["preview-leaflet"] |
Interactive map visualization viewer using Leaflet library for geographic data, markers, routes, and custom overlays.
When the user asks to create a map visualization, write the Leaflet code and pipe it to the script. Use the Bash tool to execute this skill's run.sh script:
# Pipe Leaflet code
cat route.js | ./run.sh
# Or from a file
./run.sh city-map.leaflet
The script handles all HTML generation and automatically opens the result in the browser. Do NOT open the file manually to avoid duplicate tabs.
# Preview a Leaflet map file
/preview-leaflet city-map.leaflet
# Or use .map extension
/preview-leaflet route.map
# Pipe Leaflet code (preferred for temporary content)
cat route.js | /preview-leaflet
echo "const map = L.map('map').setView([51.505, -0.09], 13);" | /preview-leaflet
Best Practice: For temporary or generated maps, prefer piping over creating temporary files. This avoids cluttering your filesystem and the content is automatically cleaned up.
The script works with sensible defaults but supports these flags for flexibility:
-o, --output PATH - Custom output path--no-browser - Skip browser, output file path onlyUse this skill when the user wants to:
Your code should:
L.map('map').setView([lat, lng], zoom)Your code runs with:
L#map sized and ready in DOM// Initialize map centered on London
const map = L.map('map').setView([51.505, -0.09], 13);
// Add OpenStreetMap tiles (REQUIRED - map is blank without this)
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors',
maxZoom: 18,
}).addTo(map);
// Add a marker
L.marker([51.505, -0.09]).addTo(map).bindPopup('Hello World!').openPopup();
// Initialize map
const map = L.map('map').setView([40.7128, -74.006], 12);
// Add tiles (REQUIRED)
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors',
maxZoom: 18,
}).addTo(map);
// Define route points
const route = [
[40.7128, -74.006], // New York
[40.758, -73.9855], // Times Square
[40.7614, -73.9776], // Central Park
];
// Draw route
L.polyline(route, {
color: 'red',
weight: 3,
}).addTo(map);
// Add markers
route.forEach((point, i) => {
L.marker(point)
.addTo(map)
.bindPopup(`Stop ${i + 1}`);
});
// Fit map to show all points
map.fitBounds(L.latLngBounds(route), { padding: [50, 50] });
// Simple marker
L.marker([51.5, -0.09]).addTo(map);
// With popup
L.marker([51.5, -0.09]).addTo(map).bindPopup('Location name');
// Circle marker (fixed pixel size)
L.circleMarker([51.5, -0.09], {
radius: 8,
fillColor: '#3498db',
color: 'white',
weight: 2,
fillOpacity: 0.9,
}).addTo(map);
// Polyline (route/path)
L.polyline(
[
[51.5, -0.09],
[51.51, -0.08],
[51.52, -0.07],
],
{
color: 'red',
weight: 3,
}
).addTo(map);
// Polygon (area)
L.polygon(
[
[51.5, -0.09],
[51.51, -0.08],
[51.52, -0.09],
],
{
color: 'blue',
fillOpacity: 0.5,
}
).addTo(map);
// Circle (fixed radius in meters)
L.circle([51.5, -0.09], {
radius: 500, // meters
color: 'red',
fillOpacity: 0.5,
}).addTo(map);
// HTML in popup
marker.bindPopup(`
<div>
<h3>Location Name</h3>
<p>Description here</p>
</div>
`);
// Tooltip (shows on hover)
marker.bindTooltip('Tooltip text', {
permanent: false,
direction: 'top',
});
// Permanent tooltip (always visible)
marker.bindTooltip('Always visible', {
permanent: true,
direction: 'right',
});
// Set view (instant)
map.setView([51.5, -0.09], 13);
// Fly to (animated)
map.flyTo([51.5, -0.09], 13, {
duration: 2, // seconds
});
// Fit bounds to show all features
const bounds = L.latLngBounds([
[51.49, -0.1],
[51.51, -0.08],
]);
map.fitBounds(bounds, {
padding: [50, 50],
});
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors',
maxZoom: 18,
}).addTo(map);
L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap, © CartoDB',
maxZoom: 18,
}).addTo(map);
L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap, © CartoDB',
maxZoom: 18,
}).addTo(map);
// Initialize map
const map = L.map('map').setView([37.7749, -122.4194], 10);
// Add tiles
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors',
}).addTo(map);
// Locations data
const locations = [
{ name: 'San Francisco', coords: [37.7749, -122.4194], type: 'city' },
{ name: 'Oakland', coords: [37.8044, -122.2712], type: 'city' },
{ name: 'Berkeley', coords: [37.8715, -122.273], type: 'city' },
];
// Add markers
locations.forEach((loc) => {
const color = loc.type === 'city' ? 'blue' : 'red';
L.circleMarker(loc.coords, {
radius: 8,
fillColor: color,
color: 'white',
weight: 2,
fillOpacity: 0.8,
})
.addTo(map)
.bindPopup(`<strong>${loc.name}</strong><br/>Type: ${loc.type}`);
});
// Fit map to show all locations
const allCoords = locations.map((loc) => loc.coords);
map.fitBounds(L.latLngBounds(allCoords), { padding: [50, 50] });
Leaflet uses [latitude, longitude] format:
Examples:
[40.7128, -74.0060][51.5074, -0.1278][35.6762, 139.6503][-33.8688, 151.2093]Common mistake: Reversing coordinates to [lng, lat] - always use [lat, lng]!
[lat, lng] not [lng, lat].addTo(map)[lat, lng] format)[latitude, longitude].addTo(map) is called on marker.leafletThe skill generates a standalone HTML file at:
.preview-skills/leaflet/{filename}.html
This skill is standalone and includes all dependencies:
lib/templates/To modify the skill:
config.sh for configurationtemplates/scripts/leaflet-renderer.js for behaviortemplates/styles/leaflet.css for stylingrun.sh to test changes