preview-leaflet

📁 veelenga/preview-skills 📅 10 days ago
4
总安装量
4
周安装量
#49040
全站排名
安装命令
npx skills add https://github.com/veelenga/preview-skills --skill preview-leaflet

Agent 安装分布

opencode 4
gemini-cli 4
qwen-code 4
claude-code 4
github-copilot 4
codex 4

Skill 文档

Preview Leaflet Skill

Interactive map visualization viewer using Leaflet library for geographic data, markers, routes, and custom overlays.

Agent Usage

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.

Usage

# 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.

Options

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 only

Features

  • Interactive maps with pan and zoom
  • Markers and popups for locations
  • Routes and paths with polylines
  • Shapes and areas with polygons and circles
  • Multiple tile layers (OpenStreetMap, CartoDB, etc.)
  • Tooltips on hover
  • Fit bounds to show all points
  • Reset view button
  • Code viewer toggle
  • Responsive design adapts to window size

When to Use This Skill

Use this skill when the user wants to:

  • Visualize geographic data on maps
  • Plot locations with markers
  • Draw routes between points
  • Show service areas or regions
  • Create interactive location-based visualizations

Leaflet Code Requirements

Your code should:

  1. Initialize the map with L.map('map').setView([lat, lng], zoom)
  2. Add a tile layer (provides map imagery)
  3. Add markers, paths, or other features

Execution Context

Your code runs with:

  • Leaflet v1.9.4 available as L
  • Map container #map sized and ready in DOM

Complete Example – Simple Map with Marker

// 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();

Complete Example – Route with Multiple Points

// 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] });

Common Patterns

Markers

// 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);

Lines and Shapes

// 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);

Popups and Tooltips

// 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',
});

View Control

// 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],
});

Tile Layers (Map Styles)

OpenStreetMap (free, default)

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: '© OpenStreetMap contributors',
  maxZoom: 18,
}).addTo(map);

CartoDB Light (clean, minimal)

L.tileLayer('https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', {
  attribution: '© OpenStreetMap, © CartoDB',
  maxZoom: 18,
}).addTo(map);

CartoDB Dark

L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png', {
  attribution: '© OpenStreetMap, © CartoDB',
  maxZoom: 18,
}).addTo(map);

Complete Example – Multiple Locations

// 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] });

Coordinate Format

Leaflet uses [latitude, longitude] format:

  • Latitude: -90 to 90 (South to North)
  • Longitude: -180 to 180 (West to East)

Examples:

  • New York: [40.7128, -74.0060]
  • London: [51.5074, -0.1278]
  • Tokyo: [35.6762, 139.6503]
  • Sydney: [-33.8688, 151.2093]

Common mistake: Reversing coordinates to [lng, lat] – always use [lat, lng]!

Built-in Features

  • Pan/zoom – Click and drag to pan, scroll to zoom
  • Zoom buttons – +/- controls in top-left
  • Reset view – Button to restore initial view
  • Code viewer – Toggle to show/hide source
  • Responsive – Automatically resizes with window

Zoom Levels

  • 1: World view
  • 5: Continent
  • 10: City
  • 15: Streets
  • 18: Buildings

Best Practices

  1. Always add tile layer – Map is blank without it
  2. Use appropriate zoom – 1 (world) to 18 (street level)
  3. Use fitBounds() for multi-point maps – Shows all features
  4. Embed data in code – Include coordinates directly
  5. Verify coordinate order[lat, lng] not [lng, lat]

Troubleshooting

Map appears blank/gray

  • Ensure tile layer is added with .addTo(map)
  • Check coordinates are valid ([lat, lng] format)
  • Verify internet connection (tiles load from CDN)
  • Check browser console for 404 errors on tiles

Markers don’t appear

  • Check coordinate format: [latitude, longitude]
  • Ensure .addTo(map) is called on marker
  • Verify coordinates are in current view
  • Try using fitBounds() to see all markers

Tiles don’t load

  • Check internet connection
  • Verify tile URL is correct
  • Look for 404 errors in browser console
  • Try a different tile provider

Wrong location shown

  • Verify coordinates are correct
  • Check coordinate order (lat first, lng second)
  • Ensure zoom level is appropriate

Technical Details

File Requirements

  • File extension: .leaflet
  • Maximum size: 10MB (configurable)
  • Valid JavaScript code
  • Self-contained (no external data files)

Browser Compatibility

  • Modern browsers (Chrome, Firefox, Safari, Edge)
  • Requires JavaScript enabled
  • Requires internet connection for tiles
  • CDN-dependent: Leaflet v1.9.4

Output

The skill generates a standalone HTML file at:

/tmp/preview-skills/preview-leaflet-{filename}.html

Development

This skill is standalone and includes all dependencies:

  • Shared libraries bundled in lib/
  • Templates bundled in templates/
  • External CDN dependencies: Leaflet v1.9.4

To modify the skill:

  1. Edit config.sh for configuration
  2. Edit templates/scripts/leaflet-renderer.js for behavior
  3. Edit templates/styles/leaflet.css for styling
  4. Run run.sh to test changes

Learn More