Jin1c62 downloadsSupercharge the built-in Maps view: GPX/GeoJSON tracks drawn from note embeds, zoom-to-fit, GCJ-02/BD-09 tile alignment, inline rendering for ![[track.gpx]], and coordinates from a pasted map link, a place search or your device.
English · 简体中文
Adds to Obsidian's built-in Maps view instead of replacing it: GPX tracks, Chinese coordinate systems, inline maps, and three ways to fill in a note's coordinates. Everything the built-in view already does — markers, icons, colours, tiles, popups — stays the built-in view doing it. No Leaflet, no vendored map library, no runtime dependencies.

| Problem | What this plugin does |
|---|---|
A note has a .gpx attached, and the map shows only a pin. |
Draws the track, in that note's colour, with start/end pins and direction arrows. |
The .gpx knows how far you walked, and nothing tells you. |
Distance, ascent, moving time and pace, with a hoverable elevation profile. |
| Mainland basemaps aren't WGS-84, so every pin floats a few streets. | Converts on the way to the map and back. Nothing on disk changes. |
| The map opens on the whole world. | Auto-frames markers and tracks, and gets out of the way once you pan. |
![[track.gpx]] renders as a link. |
Renders it as a real map, inline. |
| A map beside the note you are editing drifts away from it. | Press ⊹ and it follows the note you switch to. The base's query is never touched. |
| A trip note is about six places, and a note holds one coordinate. | One line embeds a map of the notes around it. Drag a note in and it appears. |
| A share link, and you have to dig the numbers out — in which datum? | Paste it. WGS-84 comes out, whatever went in. |
| Filling in coordinates by hand. | Search a place name, or take it from where you are — on desktop too. |
Obsidian 1.13.1+, Bases enabled, and the first-party Maps plugin — that is the view this one extends. Without it Advanced Maps says so and does nothing.
From a release. Drop main.js, manifest.json and styles.css from
Releases into
<vault>/.obsidian/plugins/advanced-maps/ and enable it.
With BRAT. Add Jin1c-3/obsidian-advanced-maps.
Attach a .gpx, .geojson, .kml or .tcx to a note and any map view whose
base includes that note draws the track. Nothing to configure, and no need to
widen a filter to let attachments into the result set.
The ! decides whether the note also gets a map of its own: ![[walk.gpx]]
gives you the line on every base map and an inline map in the note;
[[walk.gpx]] — or a track: "[[walk.gpx]]" property — gives you only the line.
Every track carries a start pin, a differently-shaped end pin, and arrows showing which way it went. Named waypoints show their name on hover, inline. Show track markers turns all of it off.

The same embed renders as a real map in the note — pan it, zoom it, switch its background — with the numbers the file was carrying all along underneath.

Distance, ascent and descent, elevation range, elapsed and moving time, pace. Whatever the file does not record is left out rather than shown as zero. Hover any number to see what it is; hover the profile and a point moves along the track on the map, and the other way round. Both the line and the profile can be switched off.
Two numbers are set the careful way: ascent ignores drift under 5 m, because raw GPS elevation is noisy enough to invent hundreds of metres of climb, and moving time counts anything above 0.9 km/h, low enough that walking up steps still counts as walking.
The built-in options are untouched; two groups are appended — Tracks behind Markers, Coordinate system behind Background.
| Option | Meaning |
|---|---|
| Line width | Track stroke width |
| Line opacity | Track stroke opacity |
| Max zoom when fitting | Upper bound for auto-fit |
| Tile coordinate system | Blank follows the plugin setting |

Both frames are the same .gpx on the same tiles. Off, the walk runs over 宝石山;
on, it lands on 白堤 — about 520 m, and every pin moves with it.
Leave it on Auto and the system is read off the tile URL: mainland hosts serving GCJ-02 or BD-09 are recognised by name, everything else is WGS-84. Set a default in settings, or force one per view when a proxied URL can't reveal where it came from.
Right-click a map. Alongside the built-in items is Open in external map.

Each app is sent the datum it expects, converted from the spot you clicked: GCJ-02 to Amap and Tencent, BD-09 to Baidu, WGS-84 or GCJ-02 to Google and Apple depending on whether the point is inside China. That is the whole difficulty — the same six links built naively land wrong in three different ways, none of them visible until you are standing in the wrong street.
Reorder the six under Open in external map in settings, switch off the ones you never reach for, or switch all six off and nothing is added to the menu. Your own starts empty; an entry is a name, a URL and the datum that URL expects:
https://ul.waze.com/ul?ll={lat},{lng}&navigate=yes WGS-84
https://www.bing.com/maps?cp={lat}~{lng}&lvl=16 WGS-84
om://map?v=1&ll={lat},{lng} WGS-84
App schemes work too — waze://, iosamap://, comgooglemaps://. The datum is
stated rather than guessed, because a mirror of a Chinese provider looks like an
ordinary host and getting it wrong does not fail, it just puts the pin a few
streets away.
You keep a single .base file, and every map in the vault is that base seen
through a different filter. Pick it once under Base file path — the box
lists the .base files in your vault. From then on it answers all three
questions a map has to settle:
| Question | Where the answer lives |
|---|---|
| Which notes count as places? | The base's own filters — a folder, a tag, a property |
| What does a pin look like? | The base's formulas, through Marker icon and Marker colour |
| Where is the coordinate? | The map view's Coordinates property |
Tune the look once and every map follows, retroactively, because none of them carry a copy of your base — they reference it. Several unrelated sets of places? A base each is fine; Base file path just names the one the commands use.
Notes carrying the coordinate property (coords by default) get an Open in map
entry on their ⋮ menu. It is your base, with your filters and icons — the camera
moves to that note and its popup opens. Nothing is copied or rewritten.

Open in picks where it lands. A tab opens the base file itself, reusing a tab already showing it, so pressing this on one note after another is a single map that keeps moving — and because it is the real file, changes you make on the map are kept. A pop-up leaves your layout alone, at the cost of having nowhere to write a view option back to.
Every map carries a ⊹ button next to zoom-to-fit. Press it and that map pans to whichever note you switch to and opens its popup. Your zoom is left alone, and the base's query is never touched: only the camera moves.

It is per map, not per plugin — a map in a sidebar and a map in the tab beside your note can follow while the one you are reading in another tab sits still. A following map also stays out of your way: the popup opens without taking the caret out of your editor, and clicking a pin opens that note in the pane the map is following rather than replacing the map with it. New maps follow the active note sets which way the button starts.
Insert a map of the notes around this one writes a single line into the note you are in:
![[places.base#Around]]

It is a view in your own base, filtered to the notes this one links to, the notes that link to it, and the note itself. Drag a note into the body — Obsidian makes a link, the way it always does — and it appears on the map. Delete the link and it goes. There is no list to keep: the links around the note are the map.
The view is added to the base the first time and referenced after that, so a later change to the base reaches every map already inserted. Two edges: the link names the view, so renaming it in Bases makes inserted maps stop resolving quietly, and the base's own filters still apply, so a note kept outside a folder-scoped base can collect other notes onto a map but not put itself on one.
A location almost never arrives as a coordinate — it arrives as a share link. Set coordinates from a map link takes one and fills the property.

It reads the share links the common mainland and international apps produce, plus
geo:30.26,120.15, DMS (30°15'39"N 120°08'49"E) and plain 30.26,120.15. Each
shape is read by its own rules, because they disagree about both axis order and
datum. Whatever goes in, WGS-84 comes out, and the datum is shown before
anything is written.
The box opens with your clipboard already in it. Shortened links hold no coordinate until they are resolved, and this plugin will not quietly hand your link to a third party to do it.
Search for a place and set coordinates looks a name up and writes what comes back, in your own Obsidian language.

Two sources: an open worldwide one that needs no signing up but is thin on mainland places, and a mainland one that needs a free web-service key and knows them far better. A source that answers in GCJ-02 is converted on the way in.
The key goes in secret storage (Obsidian's own — never synced or committed, and stays on the one device) or in plugin settings (one entry covers every device, in plain text). New installs start on secret storage; a key you had before this existed stays where it was until you move it.
Fill place name from coordinates reads the coordinate property and writes back
an address, into Place property (default location). It reuses whichever
provider and key place search is set up with. Point both settings at the same
property and it refuses rather than overwriting the coordinate it just read.
Switch on Enable location and a note whose coordinate property is present
but empty gets filled in with where you are — give a template an empty coords:
and every note made from it is stamped. Something already there is never
overwritten, and a note without the property never gains one. Fill coordinates
from current location overwrites on demand.
Values are written as lat,lng in WGS-84. Paths matching Skip paths
containing (default templates) are left alone. It works on desktop as well as
mobile, where the plugins before this one gave up — current Chromium asks the
operating system, so no API key is involved. That still needs the OS location
service on, so the plugin asks once and stops asking for the session if the
platform refuses.
Your notes and your tracks never go anywhere on their own. The one exception is a coordinate you deliberately hand to Fill place name from coordinates.
| When | What goes out | To |
|---|---|---|
| Any map is on screen | Tile requests, so your IP and the area you are looking at | Whichever background the view is set to |
| You type in the search box | The words you typed, your language, your key if you set one | The search source you picked |
| You run Fill place name from coordinates | The one coordinate you ran it on | The search source you picked |
| You pick Open in external map | The one spot you right-clicked, in that browser tab | The map app you chose, in your browser |
| You switch on Enable location | Nothing leaves — the fix comes from the operating system | — |
No telemetry, no update ping, no server of its own. Two things worth knowing if you are deploying this for other people: a search key appears in the request URL wherever you keep it — secret storage keeps it out of the settings file, not out of the query — and a note's coordinate history can be personal information in a way a note's text is not.
The screenshots were taken against third-party basemaps and search services to show what the plugin does; each image carries its source. The demo vault behind them is synthetic — the places and the trail are openly published data, and nothing personal is shown.
The plugin ships no map data of its own. It draws whatever tiles the view is configured with, and their copyright and licensing are the tile provider's and the user's. If you hold rights in anything reproduced here and would rather it were not, open an issue and it will be removed promptly.
git clone https://github.com/Jin1c-3/obsidian-advanced-maps
cd obsidian-advanced-maps
npm install
cp .env.example .env # point OBSIDIAN_PLUGIN_DIR at a vault
npm run dev # watch, rebuild into that vault, hot-reload
npm run check # prettier, eslint, tsc, vitest — the same set CI runs
npm run dev drops a .hotreload marker beside the build, which is what
pjeby/hot-reload watches for. You need a
vault with Bases on and the first-party Maps plugin installed.
New language: one object in src/i18n.ts plus one line in LOCALES. English is
the source of truth and its keys are the type, so a missing entry is a compile
error.
MIT.