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 , , , features
- 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
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 :
yaml
---
location: [40.7128, -74.0060]
---
# New York
My trip notes...
Step 3: Create the map
Create
:
markdown
```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
markdown
\`\`\`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 parameter | OpenStreetMap, city maps, GPS data |
| Image Map | | 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 | | No | Single note as marker |
| From folder | markerFolder: Path/To/Folder
| No | All notes in folder |
| From tags | | No | All notes with tag (Dataview required) |
| From links | | No | Notes linking to/from (Dataview required) |
Real-World Maps
Default tile server is OpenStreetMap. Add custom tile servers for different styles:
markdown
\`\`\`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):
markdown
tileOverlay: https://tiles.example.com/{z}/{x}/{y}.png|Overlay Name|on
Append
to enable overlay by default.
Image Maps
Critical First Step: Set Bounds
Before adding markers, define bounds to prevent coordinate confusion:
markdown
\`\`\`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:
- - Percentage-based (lat/long are percentages)
- - Pixel-based (match image dimensions)
- Custom coordinate system matching your source material
Multi-Layer Image Maps
Stack multiple images with independent marker sets:
markdown
\`\`\`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
makes map START farther away.
Why: Image is placed at
and stretched to fit. Zoom levels control the
underlying map, not the image scale.
Solution: Set bounds first, then adjust zoom to taste.
markdown
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
yaml
---
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
. Strings like
will NOT work.
Marker Methods
Single note:
markdown
markerFile: [[LocationNote]]
Folder (all notes):
markdown
markerFolder: Locations/Cities
markerFolder: Locations/Cities/ # Limit to top-level only (one slash)
By tags (⚠️ REQUIRES DATAVIEW PLUGIN):
markdown
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
lines. For AND logic: Use array
.
Filter results:
markdown
markerFolder: Locations
filterTag: #important # Only show important locations
From link relationships (⚠️ REQUIRES DATAVIEW PLUGIN):
markdown
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
in same directory:
json
[
{
"type": "city",
"icon": "building",
"color": "#FF0000",
"layer": true
},
{
"type": "dungeon",
"icon": "dungeon",
"color": "#8B4513",
"layer": true
}
]
Overlays
Circular overlays for areas of effect, regions, etc.
Interactive Creation
Shift + Right-click → drag → click to set radius
Code Block Definition
markdown
overlay: [color, [lat, long], radius unit, "description"]
Examples:
markdown
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
yaml
---
location: [50, 50]
mapoverlay: [blue, [50, 50], 25 km, "Influence zone"]
---
Or auto-generate from distance tag:
markdown
\`\`\`leaflet
overlayTag: influence
overlayColor: rgba(0,100,255,0.3)
\`\`\`
GeoJSON and GPX
GeoJSON
markdown
geojson: [[File.geojson]]|Optional Alias
geojson:
- [[Routes.geojson]]
- [[Regions.geojson]]|Regions|[[LinkedNote]]
geojsonColor: #FF0000 # Default color
GeoJSON features can include:
- , , or → tooltip
- MapBox SimpleStyle properties → styling
- Drawn in order specified (layer order matters)
GPX (GPS tracks)
markdown
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
markdown
\`\`\`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
markdown
\`\`\`leaflet
id: travel-routes
lat: 40
long: -100
gpxFolder: Travel/2024
gpxColor: #FF6600
gpxMarkers:
start: trip-start
waypoint: stop
\`\`\`
Multi-Layer Fantasy Map
markdown
\`\`\`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.,
) to specific pixels on your image.
Fix:
- Set bounds FIRST before placing any markers:
markdown
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 (lower number = closer default view)
- Use for 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 ///? → Is Dataview plugin installed AND enabled?
- Try restarting Obsidian (plugins sometimes need restart to activate)
Full checklist:
Problem: GeoJSON/GPX files not loading
Causes:
- File path incorrect (use wikilink 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 or reduce overlay radius
- Markers below overlay: Markers from / draw AFTER overlays in code block
Problem: Custom tile server not working
Checklist:
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:
markdown
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
markdown
coordinates: [[CityNote]] # Note with location frontmatter
zoomTag: viewDistance # Read zoom from note's frontmatter
CityNote frontmatter:
yaml
location: [40, -100]
viewDistance: 50 miles
Marker Zoom Breakpoints
Show/hide markers at zoom levels (prevent clutter):
yaml
mapzoom: [3, 7] # Only visible between zoom 3-7
Or per-marker in code block:
markdown
marker: city,40,-100,[[Note]],"Description",3,7
Draw Mode
markdown
draw: true # Enable drawing tools
drawColor: #FF0000 # Default shape color
Right-click drawn shapes to edit/delete. Shapes saved to map instance.
Dark Mode
markdown
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