| name | obsidian-leaflet-mapping |
| description | Use when creating interactive maps in Obsidian using LeafletJS plugin - covers real-world maps, image maps, markers from notes, overlays, GeoJSON, GPX tracks, and common issues with bounds/zoom levels |
Obsidian Leaflet Mapping
Overview
The Obsidian Leaflet plugin enables interactive maps using LeafletJS without writing JavaScript. Maps are defined in code blocks with YAML parameters and can display real-world locations (OpenStreetMap), custom images (fantasy maps, floor plans), or both layered together.
Core principle: Maps are defined declaratively in markdown code blocks. The plugin handles all JavaScript - you just configure parameters.
Plugin: https://github.com/javalent/obsidian-leaflet
Prerequisites
Required:
- Obsidian Leaflet plugin (Community Plugins → Search "Leaflet")
Optional (enables advanced features):
- Dataview plugin - REQUIRED for
markerTag,filterTag,linksTo,linksFromfeatures - Basic understanding of YAML syntax for code blocks
- For real-world maps: coordinates from Google Maps, OpenStreetMap, or GPS devices
- For image maps: image file in vault, known reference measurements for scale
Quick Start: Complete Working Example
Goal: Create a map showing all notes tagged #visited
Step 1: Install plugins
- Settings → Community Plugins → Browse
- Search "Leaflet" → Install → Enable
- Search "Dataview" → Install → Enable (REQUIRED for tag-based markers)
- Restart Obsidian (recommended after installing plugins)
Step 2: Create a test note
Create New York.md:
---
location: [40.7128, -74.0060]
tags: visited
---
# New York
My trip notes...
Step 3: Create the map
Create Travel Map.md:
```leaflet
id: my-travels
markerTag: #visited
height: 500px
```
Expected result: Map displays with one marker. Click marker → opens New York note.
If markers don't appear: See troubleshooting checklist below.
When to Use
Use this skill when:
- Creating location-based navigation in vaults (world maps, city maps, building layouts)
- Visualizing geographic data from notes (locations with frontmatter)
- Displaying custom image maps with markers (RPG campaigns, story locations)
- Tracking routes with GPX files or GeoJSON
- Building interactive dashboards with spatial data
Don't use for:
- Simple image display (use standard markdown)
- Complex GIS analysis (use dedicated GIS tools)
- Real-time map editing (markers are saved to plugin data)
Quick Reference
Basic Map Structure
\`\`\`leaflet
id: unique-map-id # REQUIRED - any unique string
image: [[ImageFile.jpg]] # Image map (omit for real-world map)
lat: 50 # Initial latitude (center point)
long: 50 # Initial longitude (center point)
height: 500px # Map container height
width: 100% # Map container width
minZoom: 1 # Minimum zoom level
maxZoom: 10 # Maximum zoom level
defaultZoom: 5 # Initial zoom level
\`\`\`
Map Types
| Type | Parameters | Use Case |
|---|---|---|
| Real-World Map | Omit image parameter |
OpenStreetMap, city maps, GPS data |
| Image Map | image: [[File.jpg]] |
Fantasy maps, floor plans, custom artwork |
| Multi-Layer Image | image: [[[Layer1]], [[Layer2]]] |
Maps with toggleable overlays |
| Custom Tile Server | tileServer: <url>|<alias> |
Alternative map styles (Dark, Satellite) |
Creating Markers
| Method | Syntax | Editable | Use Case |
|---|---|---|---|
| Right-click map | Interactive UI | Yes | Manual marker placement |
| Code block | marker: type,lat,long,link,desc |
No | Fixed markers in documentation |
| From note frontmatter | markerFile: [[Note]] |
No | Single note as marker |
| From folder | markerFolder: Path/To/Folder |
No | All notes in folder |
| From tags | markerTag: #location |
No | All notes with tag (Dataview required) |
| From links | linksTo: [[Note]] |
No | Notes linking to/from (Dataview required) |
Real-World Maps
Default tile server is OpenStreetMap. Add custom tile servers for different styles:
\`\`\`leaflet
id: city-map
tileServer: https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png|Dark
tileServer: https://tiles.wmflabs.org/hillshading/{z}/{x}/{y}.png|Hills
osmLayer: false # Turn off default OpenStreetMap layer
\`\`\`
Tile overlays (instead of full layer replacement):
tileOverlay: https://tiles.example.com/{z}/{x}/{y}.png|Overlay Name|on
Append |on to enable overlay by default.
Image Maps
Critical First Step: Set Bounds
Before adding markers, define bounds to prevent coordinate confusion:
\`\`\`leaflet
id: fantasy-map
image: [[WorldMap.jpg]]
bounds:
- [0, 0] # Top-left corner
- [100, 100] # Bottom-right corner
\`\`\`
Without bounds, the image stretches to fit arbitrary coordinates. With bounds, latitude/longitude map predictably to image pixels.
Common bound strategies:
[0,0] to [100,100]- Percentage-based (lat/long are percentages)[0,0] to [width,height]- Pixel-based (match image dimensions)- Custom coordinate system matching your source material
Multi-Layer Image Maps
Stack multiple images with independent marker sets:
\`\`\`leaflet
id: layered-map
image:
- [[BaseMap.jpg|Base Layer]]
- [[Roads.png|Roads]]
- [[Buildings.png|Buildings]]
\`\`\`
Layer control box (top-right) toggles layers. Markers saved per-layer.
Zoom Levels on Image Maps
Counter-intuitive behavior: Higher maxZoom makes map START farther away.
Why: Image is placed at [0,0] and stretched to fit. Zoom levels control the underlying map, not the image scale.
Solution: Set bounds first, then adjust zoom to taste.
bounds: [[0,0], [100,100]]
minZoom: 1
maxZoom: 6
defaultZoom: 3
zoomDelta: 0.5 # Finer zoom control
Markers from Notes
Marker behavior: Clicking a linked marker opens the note (Ctrl/Cmd-click for new pane). Markers automatically link to their source note when created via frontmatter.
Finding Coordinates
Real-world maps:
- Google Maps: Right-click location → First line shows coordinates
- OpenStreetMap: Share button → "Geo URI" contains coordinates
- GPS device: Export waypoint coordinates
Image maps:
- Use
bounds: [[0,0], [100,100]]for percentage system - Right-click map after bounds set → coordinates shown on click
- Trial-and-error: Place marker, adjust coordinates in frontmatter
Note Frontmatter Format
---
location: [lat, long] # REQUIRED for automatic markers (array format only)
mapmarker: custom-icon # Optional: marker type from settings
mapzoom: [minZoom, maxZoom] # Optional: visibility breakpoints
mapmarkers: # Optional: additional markers
- [type, [lat, long], "Description", minZoom, maxZoom]
- [type, [lat, long], "Another marker"]
---
Coordinate format: Must be array [lat, long]. Strings like "40.7128, -74.0060" will NOT work.
Marker Methods
Single note:
markerFile: [[LocationNote]]
Folder (all notes):
markerFolder: Locations/Cities
markerFolder: Locations/Cities/ # Limit to top-level only (one slash)
By tags (⚠️ REQUIRES DATAVIEW PLUGIN):
markerTag: #location # Notes with this tag
markerTag: [#city, #visited] # Notes with BOTH tags
markerTag:
- #location # Notes with #location OR
- [#city, #capital] # Notes with both #city AND #capital
For OR logic: Use separate markerTag lines. For AND logic: Use array [#tag1, #tag2].
Filter results:
markerFolder: Locations
filterTag: #important # Only show important locations
From link relationships (⚠️ REQUIRES DATAVIEW PLUGIN):
linksTo: [[MainCity]] # All notes linking to MainCity
linksFrom: [[TravelLog]] # All notes linked from TravelLog
Multiple files: linksTo: [[[File1]], [[File2]]]
Custom Marker Types
Define in plugin settings or markers.json in same directory:
[
{
"type": "city",
"icon": "building",
"color": "#FF0000",
"layer": true
},
{
"type": "dungeon",
"icon": "dungeon",
"color": "#8B4513",
"layer": true
}
]
Then use in frontmatter: mapmarker: city
Overlays
Circular overlays for areas of effect, regions, etc.
Interactive Creation
Shift + Right-click → drag → click to set radius
Code Block Definition
overlay: [color, [lat, long], radius unit, "description"]
Examples:
overlay: [blue, [32, -89], 25 mi, 'Capital region']
overlay:
- ['rgb(255,0,0)', [50, 50], 10 km, 'Danger zone']
- ['#00FF00', [60, 60], 500 ft, 'Safe area']
Note: Overlays draw in order. Smaller overlays behind larger ones become non-interactive.
Overlays from Note Frontmatter
---
location: [50, 50]
mapoverlay: [blue, [50, 50], 25 km, "Influence zone"]
---
Or auto-generate from distance tag:
\`\`\`leaflet
overlayTag: influence
overlayColor: rgba(0,100,255,0.3)
\`\`\`
Note frontmatter: influence: 50 km
GeoJSON and GPX
GeoJSON
geojson: [[File.geojson]]|Optional Alias
geojson:
- [[Routes.geojson]]
- [[Regions.geojson]]|Regions|[[LinkedNote]]
geojsonColor: #FF0000 # Default color
GeoJSON features can include:
title,description, orname→ tooltip- MapBox SimpleStyle properties → styling
- Drawn in order specified (layer order matters)
GPX (GPS tracks)
gpx: [[Track.gpx]]
gpx:
- [[Hike1.gpx]]
- [[Hike2.gpx]]
gpxColor: #00FF00
gpxMarkers:
start: start-marker-type # From plugin settings
waypoint: waypoint-type
GPX files show:
- Route line (colored by speed/elevation/heartrate if data present)
- Optional start/end/waypoint markers
- Interactive datapoint display (click track)
Common Patterns
Campaign Map with Location Notes
\`\`\`leaflet
id: campaign-world
image: [[WorldMap.jpg]]
bounds: [[0,0], [100,100]]
markerFolder: Locations/Cities
markerFolder: Locations/Dungeons
markerTag: #location
filterTag: #visited
defaultZoom: 3
\`\`\`
Travel Dashboard with GPX
\`\`\`leaflet
id: travel-routes
lat: 40
long: -100
gpxFolder: Travel/2024
gpxColor: #FF6600
gpxMarkers:
start: trip-start
waypoint: stop
\`\`\`
Multi-Layer Fantasy Map
\`\`\`leaflet
id: kingdom-map
image:
- [[Base.jpg|Terrain]]
- [[Political.png|Borders]]
- [[Trade.png|Routes]]
bounds: [[0,0], [1000,1000]]
markerTag: #city
overlayTag: territory
overlayColor: rgba(100,100,255,0.2)
\`\`\`
Common Mistakes
Problem: Markers appear in wrong locations on image maps
Cause: No bounds defined. Without bounds, Leaflet uses arbitrary coordinate space and your image stretches unpredictably.
Why this happens: Image maps overlay images onto Leaflet's default coordinate system. Without explicit bounds, the plugin has no way to map your coordinates (e.g., [50, 50]) to specific pixels on your image.
Fix:
- Set bounds FIRST before placing any markers:
bounds: [[0,0], [100,100]]
- Delete existing markers (they're in wrong coordinate system)
- Place markers again - they'll now appear where you click
Finding correct coordinates on image: After setting bounds, Shift+click map to see coordinates, use those in frontmatter.
Problem: Can't zoom in enough / Map starts too far away
Cause: Image maps: zoom controls underlying map, not image scale
Fix:
- Set bounds to match coordinate system
- Adjust
maxZoom(lower number = closer default view) - Use
zoomDelta: 0.5for finer control
Problem: Markers from notes not appearing
Quick diagnostic:
- Open note with location → does frontmatter show
location: [40.7128, -74.0060]? (array format) - Using
markerTag/filterTag/linksTo/linksFrom? → Is Dataview plugin installed AND enabled? - Try restarting Obsidian (plugins sometimes need restart to activate)
Full checklist:
- Note has
location: [lat, long]in frontmatter (exact format - array only, not string) - Tags work for both YAML (
tags: visited) and inline (#visitedin note body) - Coordinates are within map bounds (check min/max lat/long)
- Using
markerTag,filterTag,linksTo, orlinksFrom? Dataview plugin must be installed and enabled (hard dependency) - Verify Dataview works: Create a note with
dataviewcode block to confirm plugin active - Using
filterTag? Check note has ALL required tags - Marker zoom breakpoints (
mapzoom) within map'sminZoom/maxZoom? - For real-world maps: valid lat/long (lat: -90 to 90, long: -180 to 180)
- For image maps: coordinates match your bounds system
- Map doesn't specify
lat/long/defaultZoom? Default centers on [50% world map]. AddshowAllMarkers: trueto auto-fit all markers.
Problem: GeoJSON/GPX files not loading
Causes:
- File path incorrect (use wikilink
[[file.geojson]]or relative path) - Large files slow rendering (check console for errors)
- JSON syntax errors in GeoJSON
Fix: Validate GeoJSON at https://geojsonlint.com/
Problem: Overlays not interactive / Markers hidden under overlay
Cause: Drawing order matters. Overlays and markers drawn later appear on top.
Fix:
- Overlays obscuring other overlays: Reorder in code block (larger overlays last)
- Overlays obscuring markers: Use semi-transparent colors
rgba(255,0,0,0.3)or reduce overlay radius - Markers below overlay: Markers from
markerTag/markerFolderdraw AFTER overlays in code block
Problem: Custom tile server not working
Checklist:
- URL contains
{z},{x},{y}placeholders - Server allows public access (no API key required)
- Using
tileOverlayinstead oftileServerif layering over base map - Check browser console for CORS or 404 errors
Distances and Measurements
Display distance between two points:
- Shift/Alt + click location 1
- Shift/Alt + click location 2
- Distance appears in bottom-left control box
Scale and units:
unit: miles # Display unit
scale: 1.5 # Scale factor for image maps
For image maps, measure a known distance on your image, calculate scale:
scale = real_distance / measured_pixel_distance
Advanced Features
Initial View from Note
coordinates: [[CityNote]] # Note with location frontmatter
zoomTag: viewDistance # Read zoom from note's frontmatter
CityNote frontmatter:
location: [40, -100]
viewDistance: 50 miles
Marker Zoom Breakpoints
Show/hide markers at zoom levels (prevent clutter):
mapzoom: [3, 7] # Only visible between zoom 3-7
Or per-marker in code block:
marker: city,40,-100,[[Note]],"Description",3,7
Draw Mode
draw: true # Enable drawing tools
drawColor: #FF0000 # Default shape color
Right-click drawn shapes to edit/delete. Shapes saved to map instance.
Dark Mode
darkMode: true # CSS filter inversion
Customize in CSS snippet targeting .leaflet-container .dark-mode
Real-World Impact
Use cases from community:
- TTRPG campaigns: World maps with 100+ location notes, auto-updating as players discover areas
- Research: GeoJSON datasets visualized with linked analysis notes
- Travel journals: GPX tracks from Apple Health + journal entries as markers
- Urban planning: Building layouts with image overlays for different floors
- Story writing: Character location tracking across plot timeline
Performance notes:
- 50+ markers: Minimal impact
- 200+ markers: Noticeable load time
- Large GeoJSON/GPX: Consider splitting files
- Multiple maps per note: Works fine, independent instances