Geo-Daten automatisch in Obsidian-Notizen übernehmen
Beim Arbeiten mit der Maps-Erweiterung für „Bases“ stößt du relativ schnell an den Punkt, dass du Geo-Koordinaten für eine deiner Notizen brauchst, damit diese in einer „Base Map“ als Datenpunkt erscheint.
Da die Funktion „New Note“ im Kontextmenü auf einer Obsidian „Base Map“ keine Vorlage beim Erstellen einer Notiz in einem speziellen Ordner verwenden kann, suchte ich eine andere Möglichkeit, eine Notiz einfach mit Geo-Informationen in den Eigenschaften zu versorgen.
Da aber im Kontextmenü auf der Karte die Möglichkeit besteht, die Koordinaten eines Punktes in die Zwischenablage zu kopieren, kam ich auf die Idee, ein Skript zu erstellen, dass diese dann einem Service übergibt, der die relevanten Daten wie den entsprechenden Ort, die Region und ggf. die Adresse oder den POI in eine aktive Notiz im Frontmatter als Eigenschaften einträgt.
Das Skript habe ich nicht selbst geschrieben, sondern zusammen mit ChatGPT erarbeitet und getestet. Der Auftrag war, für die Verwendung von Frontmatter ein Skript zu schreiben, das dann Folgendes leistet:
- Die Zwischenablage verarbeiten und die Koordinaten aufbereiten
- Diese Koordinaten an einen Geo-Information-Service senden, um die Informationen zu Stadt, Region, Adresse oder POI zu erfragen
- Die erhaltenen Daten in das Frontmatter der aktuellen Notiz schreiben
Der Service von „nominatim.openstreetmap.org“ basiert auf Daten von „OpenStreetMap“ und wurde von ChatGPT ausgewählt.
Hier nun ein Beispiel, wie die Geo-Daten als Eigenschaften dann aussehen sollen:
coordinates:
- "49.9843"
- "7.8562"
ort: "Weingut Müller-Catoir"
stadt: "Neustadt an der Weinstraße"
region: "Rheinland-Pfalz"
land: "Deutschland"
adresse: "Weingut Müller-Catoir, ... , Rheinland-Pfalz, Deutschland"
#Wie funktioniert das Skript?
Wie schon erwähnt, besteht das Skript im Kern aus drei aufeinander aufbauenden Schritten. Diese Schritte sorgen dafür, dass aus einer kopierten Koordinate strukturierte Eigenschaften im Frontmatter einer Notiz entstehen.
Im ersten Schritt wird der Inhalt der Zwischenablage verarbeitet. Die Koordinaten, die zum Beispiel aus einer „Base Map“ oder aus Google Maps kopiert wurden, werden bereinigt und in ein einheitliches Format gebracht, damit sie zuverlässig weiterverarbeitet werden können.
Im zweiten Schritt werden diese aufbereiteten Geo-Koordinaten an den Nominatim Web Service übergeben, der auf Basis von „OpenStreetMap“ Daten die Informationen zu einer Geo-Koordinate abfragt und als Ergebnis ein JSON liefert, das weiterverarbeitet werden kann.
Im dritten Schritt schreibt das Skript die ermittelten Daten in das Frontmatter der aktuell aktiven Notiz. Dadurch stehen die Informationen sofort als Eigenschaften zur Verfügung und können in „Bases“ zur Darstellung in der Karte verwendet werden.
Je nachdem, was „Nominatim“ zu den Geo-Koordinaten findet, kann das Skript folgende Eigenschaften setzen:
- coordinates: Die Koordinaten werden in die Notiz geschrieben, damit sie auf der Karte angezeigt werden kann. Sie liegen bereits in der Zwischenablage vor und müssen daher nicht erst über den Geo-Information-Service ermittelt werden.
- ort: Wenn bei dieser Koordinate ein besonderer Ort in „OpenStreetMap“ verzeichnet ist, wird der Name dieses Ortes als Wert dieser Eigenschaft in die Notiz geschrieben. Wenn die Abfrage keinen Ort findet, bleibt die Eigenschaft ohne Wert.
- ort_type: Die Abfrage von „OpenStreetMap“ gibt auch den Typ des Objektes zurück, z. B. „kindergarten“. Leider ist der Typ immer auf Englisch, trotzdem habe ich ihn hier aufgenommen.
- stadt: An dieser Stelle trägt das Skript den Namen der Stadt ein, falls es eine Stadt ermitteln konnte.
- region: Diese Eigenschaft wird in Deutschland mit dem Bundesland der Koordinate gefüllt.
- land: Hier wird das Land eingetragen.
- adresse: An dieser Stelle wird zusätzlich die gesamte Adresse der Koordinate eingetragen.
Damit du dieses Skript verwenden kannst, musst du die externe Erweiterung „Templater“ installieren. Wie du „Templater“ installierst und auch eine kleine Erklärung dieser Erweiterung findest du hier: Tägliche Notizen mit Vorlagen, Calendar & Templater
Wenn du nun „Templater“ installiert hast, können wir anfangen. Falls du mein Beispiel Vault „Obsidian4Maps“ heruntergeladen hast und verwendest, ist das alles schon integriert.
Wenn nicht, musst du als Erstes eine Vorlage mit dem Skript erstellen, dann diese Vorlage der „Templater“ Erweiterung bekannt machen und am besten mit einem Tastenkürzel versehen. Danach kannst du jeder Notiz, die gerade aktiv ist, die oben genannten Eigenschaften und deren Werte mit einem Tastenkürzel direkt hinzufügen, sofern in der Zwischenablage Koordinaten in der Form 49.08982, 7.14829 vorhanden sind. Diese kannst du übrigens nicht nur aus der „Base Map“ heraus kopieren, sondern auch aus Google Maps, auch hier über das Kontextmenü.
Im nächsten Abschnitt geht es dann in den Code.
#Das Skript
Wie schon erwähnt, hat ChatGPT dieses Skript nach meinen Anweisungen erstellt. Gerade deshalb lohnt es sich, es etwas genauer anzuschauen. Das hat im Wesentlichen zwei Gründe: Zum einen sollte man grob verstehen, was so ein generierter Code macht. Zum anderen kann man dabei auch selbst lernen, wenn man sich den Code Schritt für Schritt anschaut.
Der Aufbau des Skripts orientiert sich dabei an vier klaren Abschnitten, die wir im Folgenden auch einzeln durchgehen:
- Die Zwischenablage lesen und die Geo-Koordinaten extrahieren
- Reverse-Geocoding über „Nominatim“ und „OpenStreetMap“
- Das Frontmatter der aktuellen Notiz aktualisieren
- Rückmeldung und Erfolgsmeldung
#Die Zwischenablage lesen und die Geo-Koordinaten extrahieren
Auch wenn du dich, wie auch ich, nicht unbedingt mit JavaScript auskennst, ist der Code doch gut verständlich, zumindest mit etwas Erklärung.
// Clipboard als String lesen (await ist bei einigen Templater-Versionen nötig)
const clip = '' + await tp.system.clipboard();
// Aus dem Clipboard alle Zahlen extrahieren (robust gegen Formate wie:
// "49.21, 8.70", "Lat: 49.21 Lng: 8.70", "(49.21 8.70)" usw.)
const nums = clip.match(/-?\d+(?:\.\d+)?/g) ?? [];
// Wir nehmen die ersten zwei gefundenen Zahlen als lat/lon
const lat = nums[0];
const lon = nums[1];
// Wenn wir nicht mindestens zwei Zahlen haben, brechen wir ab
if (!lat || !lon) {
new Notice("Keine gültigen Koordinaten im Clipboard gefunden");
return;
}
Zunächst wird die Zwischenablage, also das Clipboard, mit der „Templater“ Funktion tp.system.clipboard in die Konstante clip geschrieben. Dabei stellt das await sicher, dass die Funktion auch wirklich Daten zurückliefert. Die Verkettung mit '' + setzt die Konstante explizit auf den Typ String, bevor die eigentlichen Daten übernommen werden.
Der Aufruf const nums = clip.match(/-?\d+(?:\.\d+)?/g) ?? []; extrahiert mit einem regulären Ausdruck die beiden Zahlen, also die Koordinaten, und erzeugt daraus ein Array mit zwei Werten. Diese werden anschließend den Konstanten lat und lon zugeordnet. nums[0] holt das erste Element aus dem Array und nums[1] das zweite. In JavaScript beginnt die Zählung, wie in vielen anderen Programmiersprachen auch, bei 0.
Falls in den Konstanten lat oder lon kein Wert steht, wird das Skript mit einer entsprechenden Meldung beendet.
#OpenStreetMap-Daten über „Nominatim" abfragen und für die Weiterverarbeitung aufbereiten
Dieser Teil ist etwas komplexer. Zunächst werden die Variablen für die Eigenschaften adresse, ort, ort_type, stadt, region und land als String initialisiert.
Danach wird die URL definiert, die für den Aufruf des Services notwendig ist.
Der Konstanten url wird ein Service-Aufruf vom Typ reverse zugewiesen. Da du bereits die Koordinaten kennst und die zugehörigen Adressinformationen ermitteln möchtest, ist dieser Aufruf sinnvoll. Die Details zu diesem Aufruf findest du in der Dokumentation von Nominatim.
Die weiteren Parameter sind dann:
format=jsonv2: Legt fest, in welchem Format die Antwort zurückgegeben wird.latundlon: Übergabe der geografischen Breite und Länge aus der Zwischenablage.zoom=18: Hohe Detailtiefe für POIs, Gebäude und Einrichtungen.addressdetails=1: Liefert strukturierte Adressfelder.
// ------------------------------------------------------------
// 2) OpenStreetMap-Daten über Nominatim abfragen und aufbereiten
// ------------------------------------------------------------
let adresse = "";
let ort = "";
let ort_type = "";
let stadt = "";
let region = "";
let land = "";
try {
const url =
`https://nominatim.openstreetmap.org/reverse?format=jsonv2` +
`&lat=${encodeURIComponent(lat)}` +
`&lon=${encodeURIComponent(lon)}` +
`&zoom=18` +
`&addressdetails=1`;
const res = await requestUrl({
url,
method: "GET",
headers: {
"User-Agent": "Obsidian-Templater"
}
});
const data = res.json;
const a = data?.address ?? {};
if (typeof data?.display_name === "string") {
adresse = data.display_name;
}
if (typeof data?.type === "string") {
ort_type = data.type;
}
const addresstype = data?.addresstype;
ort =
(typeof data?.name === "string" ? data.name : "") ||
(addresstype && typeof a?.[addresstype] === "string" ? a[addresstype] : "") ||
(typeof a?.amenity === "string" ? a.amenity : "") ||
(typeof a?.tourism === "string" ? a.tourism : "") ||
(typeof a?.shop === "string" ? a.shop : "") ||
(typeof a?.leisure === "string" ? a.leisure : "") ||
(typeof a?.building === "string" ? a.building : "") ||
(typeof a?.railway === "string" ? a.railway : "") ||
"";
stadt =
a.city ||
a.town ||
a.village ||
a.hamlet ||
"";
region =
a.state ||
a.region ||
a.county ||
"";
land = a.country || "";
} catch (e) {
console.error(e);
new Notice("Adresse konnte nicht geladen werden (Internet/API)");
}
Diese Antwort wird zunächst an die Konstante data übergeben. Zusätzlich wird dann der address Teil als JSON noch der Konstante a zugeordnet. Das vereinfacht die Schreibweise bei der Zuordnung der Felder unter address, da statt data.address.city einfach a.city geschrieben werden kann. Das ist für die Funktion nicht zwingend notwendig, erhöht aber die Lesbarkeit des Codes deutlich.
Nun folgen die Zuordnungen zu einzelnen Variablen. Ein Problem ist dabei, dass „Nominatim“ nicht jedes Mal die gleichen Antwortstrukturen liefert. Daher werden im Skript verschiedene Möglichkeiten ausprobiert, bis ein Schlüssel auch einen Wert enthält:
ort =
(typeof data?.name === "string" ? data.name : "") ||
(addresstype && typeof a?.[addresstype] === "string" ? a[addresstype] : "") ||
(typeof a?.amenity === "string" ? a.amenity : "") ||
(typeof a?.tourism === "string" ? a.tourism : "") ||
(typeof a?.shop === "string" ? a.shop : "") ||
(typeof a?.leisure === "string" ? a.leisure : "") ||
(typeof a?.building === "string" ? a.building : "") ||
(typeof a?.railway === "string" ? a.railway : "") ||
"";
In diesem Code-Snippet wird zunächst geprüft, ob data?.name einen Text als Inhalt hat. Ist das der Fall, wird dieser Wert übernommen. Die beiden || bedeuten, dass die Abfragen mit einem „oder“ verbunden sind. Sobald eine der Abfragen einen gültigen Wert liefert, wird diese Bedingung „wahr“ und deshalb werden die weiteren Bedingungen nicht mehr ausgewertet.
Das gleiche Prinzip wird auch bei der Ermittlung der Stadt verwendet:
stadt =
a.city ||
a.town ||
a.village ||
a.hamlet ||
"";
Hier ist keine zusätzliche typeof Prüfung mehr notwendig, da a bereits bei der Initialisierung als Objekt oder als leeres Objekt gesetzt wurde. Dadurch ist sichergestellt, dass Zugriffe wie a.city oder a.town keinen Fehler auslösen, sondern zunächst undefined zurückgeben, falls das Feld nicht existiert. Sind alle geprüften Felder undefined, wird der Variablen stadt am Ende ein leerer String zugeordnet.
#Das Frontmatter mit den ermittelten Werten aktualisieren
Zunächst wird der Konstanten file die aktuell geöffnete Datei als Objekt übergeben. Damit wissen die folgenden Funktionen, mit welcher Notiz sie arbeiten sollen.
// Aktuelle Datei ermitteln
const file = tp.file.find_tfile(tp.file.path(true));
Anschließend wird der YAML Teil der Notiz für die Bearbeitung geöffnet:
// processFrontMatter kümmert sich darum, YAML korrekt zu schreiben
await app.fileManager.processFrontMatter(file, (frontmatter) => {
Dieser Aufruf stellt sicher, dass das YAML syntaktisch korrekt bleibt, auch wenn Eigenschaften geändert oder neu hinzugefügt werden. Vorhandene Eigenschaften werden dabei mit neuen Werten überschrieben, sofern entsprechende Werte vorhanden sind.
Innerhalb dieser Funktion werden nun die einzelnen Eigenschaften gesetzt:
// Koordinaten als Liste speichern. Strings sind ok und stabil in YAML.
frontmatter.coordinates = [lat, lon];
// Adresse nur setzen, wenn wir wirklich etwas bekommen haben
if (adresse) frontmatter.adresse = adresse;
// Ort und Ort-Typ setzen, wenn vorhanden
if (ort) frontmatter.ort = ort;
if (ort_type) frontmatter.ort_type = ort_type;
// Strukturierte Felder sind später sehr nützlich für Bases/Dataview
if (stadt) frontmatter.stadt = stadt;
if (region) frontmatter.region = region;
if (land) frontmatter.land = land;
});
Für die Geo-Koordinaten wird die Eigenschaft coordinates immer gesetzt oder überschrieben. Falls sie in der Notiz noch nicht existiert, wird sie automatisch angelegt.
Bei allen anderen Eigenschaften wird zunächst geprüft, ob überhaupt ein Wert vorhanden ist. Nur dann wird die entsprechende Eigenschaft geschrieben. Ist kein Wert vorhanden, bleibt eine bestehende Eigenschaft unverändert und wird nicht neu angelegt. Damit wird verhindert, dass vorhandene Metadaten durch leere Werte überschrieben werden.
Wenn das Frontmatter aktualisiert wurde, gibt das Skript zum Schluss noch eine kurze Rückmeldung in Obsidian aus.
#Rückmeldung und Erfolgsmeldung
Nachdem das Frontmatter aktualisiert wurde, gibt das Skript zum Schluss noch eine kurze Rückmeldung in Obsidian aus. Ein ähnlicher Aufruf wurde bereits am Anfang des Skripts verwendet, falls keine gültigen Geo-Koordinaten im Clipboard gefunden wurden.
new Notice("Koordinaten und Geo-Daten wurden gesetzt");
Wenn alles erfolgreich war, wurden die Eigenschaften der Notiz entsprechend ergänzt. In diesem Beispiel wurde die Notiz zum Bundeskanzleramt neben den bestehenden Eigenschaften um die hervorgehobenen Werte erweitert:

Diese Rückmeldung ist bewusst schlicht gehalten. Sie signalisiert, dass das Skript ohne Fehler durchgelaufen ist und die Daten in die aktuelle Notiz geschrieben wurden.
Im nächsten Schritt findest du das vollständige Skript noch einmal zusammenhängend, sodass du es direkt in deinen Vorlagen Ordner übernehmen kannst.
#Das Skript als Vorlage einrichten und verwenden
Hier findest du nun das gesamte Skript, das du in deinem Vorlagen Ordner in einer neuen Notiz ablegst. Diese Notiz sollte sonst keinen weiteren Inhalt enthalten. Ich habe sie in meinem Vault „Geo Information“ genannt.
<%*
/*
----------------------------------------------------------------------
TEMPLATER SCRIPT: Koordinaten aus Clipboard + Reverse-Geocoding (OSM)
----------------------------------------------------------------------
Zweck
1. Koordinaten aus dem Clipboard lesen (z. B. aus Obsidian Maps)
2. Über Nominatim (OpenStreetMap) Reverse-Geocoding machen
3. Frontmatter der aktuell geöffneten Notiz aktualisieren:
- coordinates: [lat, lon] (als Liste von Strings)
- adresse: display_name (lesbare Gesamtadresse)
- ort: Name des konkreten Ortes/POI (z. B. "St.Ulrich")
- ort_type: OSM-Typ des Objekts (z. B. "kindergarten")
- stadt: Stadt / Town / Village usw.
- region: Bundesland/Kanton/State (Fallback: County)
- land: Land
Hinweise
- Nominatim ist ein freier Dienst mit Fair-Use. Für manuelle Nutzung ok.
- Ohne Internet klappt nur das Setzen der Koordinaten, Adresse bleibt leer.
- Das Script überschreibt vorhandene Felder, wenn es neue Werte hat.
*/
// ------------------------------------------------------------
// 1) Clipboard lesen und Koordinaten extrahieren
// ------------------------------------------------------------
// Clipboard als String lesen (await ist bei einigen Templater-Versionen nötig)
const clip = '' + await tp.system.clipboard();
// Aus dem Clipboard alle Zahlen extrahieren (robust gegen Formate wie:
// "49.21, 8.70", "Lat: 49.21 Lng: 8.70", "(49.21 8.70)" usw.)
const nums = clip.match(/-?\d+(?:\.\d+)?/g) ?? [];
// Wir nehmen die ersten zwei gefundenen Zahlen als lat/lon
const lat = nums[0];
const lon = nums[1];
// Wenn wir nicht mindestens zwei Zahlen haben, brechen wir ab
if (!lat || !lon) {
new Notice("Keine gültigen Koordinaten im Clipboard gefunden");
return;
}
// ------------------------------------------------------------
// 2) Reverse Geocoding über Nominatim (OpenStreetMap)
// ------------------------------------------------------------
// Zielvariablen, die wir später ins Frontmatter schreiben
let adresse = "";
let ort = "";
let ort_type = "";
let stadt = "";
let region = "";
let land = "";
try {
// zoom=18: eher detailreich (POIs/Gebäude) statt nur Stadt/Gemeinde
// addressdetails=1: liefert den address-Block
// jsonv2: gut strukturiert
const url =
`https://nominatim.openstreetmap.org/reverse?format=jsonv2` +
`&lat=${encodeURIComponent(lat)}` +
`&lon=${encodeURIComponent(lon)}` +
`&zoom=18` +
`&addressdetails=1`;
// Obsidian stellt requestUrl global bereit
const res = await requestUrl({
url,
method: "GET",
headers: {
// Fair-Use: eigener User-Agent ist wichtig
"User-Agent": "Obsidian-Templater"
}
});
const data = res.json;
const a = data?.address ?? {};
// 2a) Ganze Adresse als lesbarer String
// display_name ist oft lang, aber praktisch als "volle" Adresse
if (typeof data?.display_name === "string") {
adresse = data.display_name;
}
// 2b) ort_type: Der "type" Wert aus Nominatim
// Beispiele: kindergarten, restaurant, wine_cellar, railway_station, ...
// Das ist NICHT die Kategorie (category), sondern das spezifischere Feld.
if (typeof data?.type === "string") {
ort_type = data.type;
}
// 2c) Ort/POI Namen extrahieren
//
// Problem: Nominatim ist nicht in allen Antworten gleich.
// Manchmal steht der Name in data.name, manchmal in address.<addresstype>.
//
// addresstype beschreibt, welches Feld in address den "Hauptnamen" enthält.
// In deinem Beispiel:
// addresstype = "amenity"
// address.amenity = "St.Ulrich"
//
// Daher nutzen wir eine robuste Reihenfolge:
// 1) data.name (wenn vorhanden)
// 2) address[data.addresstype] (falls addresstype vorhanden)
// 3) bekannte Felder als Fallback (amenity/tourism/shop/...)
const addresstype = data?.addresstype;
ort =
(typeof data?.name === "string" ? data.name : "") ||
(addresstype && typeof a?.[addresstype] === "string" ? a[addresstype] : "") ||
(typeof a?.amenity === "string" ? a.amenity : "") ||
(typeof a?.tourism === "string" ? a.tourism : "") ||
(typeof a?.shop === "string" ? a.shop : "") ||
(typeof a?.leisure === "string" ? a.leisure : "") ||
(typeof a?.building === "string" ? a.building : "") ||
(typeof a?.railway === "string" ? a.railway : "") ||
"";
// 2d) Stadt ermitteln
// Je nach Gegend wird es als city, town, village oder hamlet geliefert.
stadt =
a.city ||
a.town ||
a.village ||
a.hamlet ||
"";
// 2e) Region ermitteln (Bundesland/Kanton/State)
// Fallback: county (Landkreis)
region =
a.state ||
a.region ||
a.county ||
"";
// 2f) Land ermitteln
land = a.country || "";
} catch (e) {
// Wenn die Abfrage fehlschlägt (offline, Timeout, API blockiert),
// setzen wir trotzdem die Koordinaten. Adresse-Felder bleiben leer.
console.error(e);
new Notice("Adresse konnte nicht geladen werden (Internet/API)");
}
// ------------------------------------------------------------
// 3) Frontmatter der aktuellen Notiz aktualisieren
// ------------------------------------------------------------
// Aktuelle Datei ermitteln
const file = tp.file.find_tfile(tp.file.path(true));
// processFrontMatter kümmert sich darum, YAML korrekt zu schreiben
await app.fileManager.processFrontMatter(file, (frontmatter) => {
// Koordinaten als Liste speichern. Strings sind ok und stabil in YAML.
frontmatter.coordinates = [lat, lon];
// Adresse nur setzen, wenn wir wirklich etwas bekommen haben
if (adresse) frontmatter.adresse = adresse;
// Ort und Ort-Typ setzen, wenn vorhanden
if (ort) frontmatter.ort = ort;
if (ort_type) frontmatter.ort_type = ort_type;
// Strukturierte Felder sind später sehr nützlich für Bases/Dataview
if (stadt) frontmatter.stadt = stadt;
if (region) frontmatter.region = region;
if (land) frontmatter.land = land;
});
// ------------------------------------------------------------
// 4) Rückmeldung
// ------------------------------------------------------------
new Notice("Koordinaten, Ort und Adresse wurden gesetzt");
%>
Nun musst du in den „Templater“ Einstellungen unter „Template Hotkeys“ (1) den Pfad (2) zu der eben erstellten Notiz angeben und über das Plus Symbol (3) die Tastenkürzel Einstellung aufrufen.

In der Tastenkürzel Einstellung suchst du nun die Vorlage mit dem Skript (1) und weist der „Templater“ Funktion „Geo Information“ (2) ein Tastenkürzel zu (3).

Wenn du prüfen möchtest, ob alles geklappt hat, indem du die Befehlspalette aufrufst und in den Filter (1) „geo info“ eingibst. Dann sollten die beiden Befehle wie unten im Bild erscheinen.

Nun bist du bereit, deine erste Notiz mit Geo-Daten zu versehen.
#Die Verwendung
Nachdem nun das Skript aufrufbar ist, öffnest du eine „Base Map“ oder Google Maps und kopierst die Geo-Koordinaten eines beliebigen Punktes in die Zwischenablage. Du kannst sie auch aus anderen Anwendungen kopieren. Sie sollten jedoch im Format 52.518611, 13.408333 vorliegen, also Längengrad und Breitengrad als Dezimalzahlen.
Erstelle anschließend eine neue Notiz, zum Beispiel im Ordner „Städte“. Wenn die Notiz aktiv ist, rufst du den Befehl Templater: Insert Geo Informationüber die Befehlspalette oder über das zugewiesene Tastenkürzel auf.
In diesem Beispiel habe ich die Koordinaten 52.518611, 13.408333 nach einem Klick auf Berlin verwendet und folgende Daten zurückbekommen:
adresse: 15, Rathausstraße, Nikolaiviertel, Neu-Cölln, Mitte, Berlin, 10178, Deutschland
ort_type: house
stadt: Berlin
land: Deutschland
Die Ergebnisse können sind oft von minimalen Unterschieden in den „Nachkommenstellen“ abhängig, ob du tatsächlich den gewünschten POI erwischt, oder die Imbiss-Bude daneben. Da wäre es oftmals einfacher, eher die groben Geo-Daten automatische eintragen zu lassen und den Rest mit der Hand. Selbst wenn du ganz nahe in die Karte Zooms, kann es passieren, dass du als POI nicht den Bahnhof zurückbekommst, sondern den Buchhändler im Bahnhof.
Du kannst mit den Parametern zoomund addressdetailexperimentieren, indem du die Werte in dem Skript änderst oder direkt eine weitere Vorlage verwendest, welche die EIgenschaften einer Notiz nur um das Land, die Stadt und die Region erweitert. Hier wäre die abgespeckte Version des Skriptes (ligt auch im Beipiel Vault in den Vorlagen mit den Namen coordinates):
<%*
const clip = '' + await tp.system.clipboard();
const nums = clip.match(/-?\d+(?:\.\d+)?/g) ?? [];
const lat = nums[0];
const lon = nums[1];
if (!lat || !lon) {
new Notice("Keine gültigen Koordinaten im Clipboard gefunden");
return;
}
let stadt = "";
let region = "";
let land = "";
try {
const url =
`https://nominatim.openstreetmap.org/reverse?format=jsonv2` +
`&lat=${encodeURIComponent(lat)}` +
`&lon=${encodeURIComponent(lon)}` +
`&zoom=18&addressdetails=1`;
const res = await requestUrl({
url,
method: "GET",
headers: { "User-Agent": "Obsidian-Templater" }
});
const data = res.json;
const a = data?.address ?? {};
stadt = a.city || a.town || a.village || a.hamlet || "";
region = a.state || a.region || a.county || "";
land = a.country || "";
} catch (e) {
console.error(e);
new Notice("Adresse konnte nicht geladen werden");
}
const file = tp.file.find_tfile(tp.file.path(true));
await app.fileManager.processFrontMatter(file, (frontmatter) => {
frontmatter.coordinates = [lat, lon];
if (stadt) frontmatter.stadt = stadt;
if (region) frontmatter.region = region;
if (land) frontmatter.land = land;
});
new Notice("Koordinaten und Ortsdaten wurden gesetzt");
%>
Das Einbinden in die „Templater“ Erweiterung erfolgt auf die gleiche Weise wie beim vorherigen Skript. Wenn du die Vorlage unter einem anderen Namen ablegst, kannst du je nach Anwendungsfall entscheiden, ob deine Notiz mit eher groben oder mit detaillierteren Geo-Daten ergänzt wird.
#Fazit
Diese beiden Skripte sind entstanden, weil die Funktion „New Note“ auf einer Obsidian Base Map aktuell keine Vorlagen beim Erstellen neuer Notizen unterstützt. Da sich die Koordinaten eines Ortes jedoch direkt aus der Karte kopieren lassen, lag die Idee nahe, diese automatisch in strukturierte Eigenschaften einer Notiz zu überführen und bei Bedarf um weitere Ortsinformationen zu ergänzen.
Da meine eigenen Entwicklerfähigkeiten begrenzt sind, habe ich die Auswahl des passenden Services und die Erstellung des Skripts mit Unterstützung von ChatGPT umgesetzt. Für solche überschaubaren Aufgaben kann Vibecoding sehr hilfreich sein. Gleichzeitig sollte man versuchen, den erzeugten Code zumindest grob zu verstehen, auch wenn man sich nicht als Entwickler sieht. Genau deshalb habe ich das Skript in diesem Kapitel Schritt für Schritt erklärt.
Natürlich bringt diese Art von Automatisierung auch Verantwortung mit sich. Das Skript verändert Daten im Vault und greift auf einen externen Dienst zu. In diesem konkreten Fall werden jedoch ausschließlich Geo-Koordinaten aus der Zwischenablage verarbeitet, eine öffentliche API abgefragt und strukturierte Textdaten in Markdown geschrieben. Es werden keine Zugangsdaten, Tokens oder sensiblen Informationen verwendet. Die Verarbeitung ist defensiv aufgebaut und Fehler werden abgefangen, sodass keine unkontrollierten Änderungen entstehen.
Auch Templater selbst sollte man mit Bedacht einsetzen. Templates laufen mit denselben Rechten wie Obsidian und können Dateien verändern oder Netzwerkzugriffe durchführen. Deshalb empfiehlt es sich, nur eigene oder vertrauenswürdige Vorlagen zu verwenden und regelmäßige Backups des Vaults zu haben.
Ein weiterer Aspekt ist die Wartbarkeit. Für kleinere Automationen, Metadatenpflege und verbindende Logik zwischen Tools ist Templater hervorragend geeignet. Sobald Abläufe jedoch komplexer werden oder mehrere externe Dienste beteiligt sind, kann ein separates Skript oder ein eigenes Plugin langfristig die bessere Lösung sein.
Beim verwendeten Dienst „Nominatim“ gilt außerdem das Fair-Use-Prinzip. Einzelne manuelle Abfragen sind unkritisch. Automatisierte Massenabfragen oder schnelle Schleifen sollten vermieden oder entsprechend gedrosselt werden.
Insgesamt ist dieses Setup ein gutes Beispiel für einen pragmatischen Einsatz von Vibecoding im persönlichen Wissensmanagement. Lokal, transparent, nachvollziehbar und mit einem klaren praktischen Nutzen im Alltag.
Ich hoffe, das hilft dir weiter. Wenn du Fragen oder Anmerkungen hast, freue ich mich über eine Rückmeldung.