BuTzZ c9a20aacd7
Test and publish container images / test (push) Successful in 2m50s
Test and publish container images / publish (push) Failing after 54s
Reorganised deployment scripts and added rollback functionality. Updated documentation and workflow for container image builds.
2026-07-25 12:36:35 +02:00
2026-07-24 11:29:24 +02:00
2026-07-24 11:29:24 +02:00

Watermaps

iPhone-taugliche Browser-PWA für Bootsfahrer: Karte, GPS, Kompass, Wetter/Wellen, BSH-Tiden, Fahrwasser-Routing mit Bootsmaßen sowie Schleusen- und Hafeninformationen.

Funktionen

  • Routing auf See- und Binnenwasserstraßen statt Luftlinien
  • explizit gestarteter Kursassistent mit dynamischem Sollkurs über Grund, Querabweichung, Reststrecke und Kurswechsel-Hinweisen
  • zweistufige Ankerwache mit festem Ankerpunkt, GPS-Schwojkreis, Alarm, Tidenanstieg und nachvollziehbarer Ketten-/Leinenreserve
  • bis zu drei ausreichend unterschiedliche Routenvorschläge, sofern der Wasserstraßengraph echte Alternativen enthält
  • Prüfung von Tiefgang plus Sicherheitsreserve, Bootshöhe, Breite und bekannten Einbahnregeln
  • Fahrwasser-Unterstützung für die Korridore EmdenBorkum und EmdenHamm nach manueller Auswahl von Start und Ziel
  • antippbare Info-Buttons ab Kartenzoom 12 an Schleusen und Häfen mit Telefon, Website, E-Mail, VHF, Öffnungszeiten, Betreiber und Adresse, soweit in den Quelldaten vorhanden
  • Brückenhöhen, bekannte Tiefen, Wetter/Wellen, Tide, GPS und Kompass
  • frei sortierbare Zwischenziele direkt von der Karte
  • Abfahrtszeit-bezogene Wetter-, Wellen-, Strömungs- und Tidenplanung entlang der Route
  • Live-Wasserstände aus der offiziellen PEGELONLINE-API der WSV mit Cache- und Veraltet-Status
  • Tagesetappen mit Hafenwahl und Filtern für Strom, Wasser, Treibstoff, Entsorgung und Übernachtung
  • Schleusenliste entlang der Route mit bekannten Betriebszeiten/Kontakten und einstellbarem Planungspuffer
  • GPX-1.1-Export, lokal gespeicherte Offline-Routen und ein nur auf Nutzeraktion gestarteter Kursabweichungsalarm
  • begrenztes Offline-Caching bereits besuchter Kartenressourcen ohne ungefragten Kacheldownload

Start

Der reguläre lokale Betrieb läuft als einzelner Produktionscontainer. Der gemeinsame Fahrwasserindex für Deutschland und die Niederlande muss einmalig vorhanden sein:

npm run setup:local-routing
npm run docker:up

Web und API: http://localhost:5173
Healthcheck: http://localhost:5173/health

Die sichtbaren Kartenkacheln kommen weiterhin von den konfigurierten externen Kartendiensten. Lokal gespeichert werden nur die OSM-Rohdaten und der daraus erzeugte Routingindex.

Stoppen:

npm run docker:down

Für die Entwicklung ohne Container benötigt das Projekt Node >=20.19:

npm install
npm run dev

Dev-Web: http://localhost:5173
Dev-API: http://localhost:5174

Für GPS-Tests auf dem iPhone muss die App über HTTPS laufen. Starte dafür:

npm run dev:https

Web HTTPS: https://localhost:5173 bzw. die von Vite ausgegebene https://192.168...:5173-Adresse im gleichen WLAN. Beim lokalen Dev-Zertifikat muss Safari die Zertifikatswarnung einmal akzeptieren; falls iOS Geolocation danach weiterhin blockiert, nutze ein vertrauenswürdiges lokales Zertifikat oder einen HTTPS-Tunnel.

Hetzner-Deployment mit OpenTofu

Die produktive Infrastruktur besteht aus einem Hetzner-Server, einer festen IPv4, Firewall und einem persistenten Volume. Der Docker-Stack enthält nur die App, Nginx/Certbot und den Wartungscontainer für Deutschland- und Niederlande-Routendaten; Kartenkacheln werden nicht selbst gehostet. Gitea Actions testet jeden Stand und veröffentlicht App und Routingdaten-Builder für Commits auf main als Container-Images. Der Produktionsserver klont keinen Quellcode und baut keine Anwendung.

Die beiden lokalen, von Git ignorierten Konfigurationsdateien werden aus ihren Vorlagen angelegt:

cp infra/opentofu/terraform.tfvars.example infra/opentofu/terraform.tfvars
cp deploy/.env.production.example deploy/.env.production
  • infra/opentofu/terraform.tfvars: hier den Hetzner-Cloud-Read/Write-Token eintragen und admin_cidrs bei Bedarf auf die aktuelle öffentliche IP aktualisieren.
  • deploy/.env.production: hier eine echte E-Mail-Adresse für Let's Encrypt als WATERMAPS_ACME_EMAIL eintragen.

Danach wird die Infrastruktur erzeugt:

cd infra/opentofu
tofu init
tofu plan -out=watermaps.tfplan
tofu apply watermaps.tfplan
tofu output server_ipv4
cd ../..

Vor dem ersten Deployment müssen Gitea Actions, ein Docker-fähiger Runner sowie die Action-Secrets REGISTRY_USERNAME und REGISTRY_TOKEN eingerichtet sein. Der Token benötigt Schreibzugriff auf Packages. Sobald server_ipv4 ausgegeben wurde, kann der manuelle DNS-A-Record watermaps.incoso.eu auf diese IPv4 gesetzt werden. Das erste Deployment darf bereits vor der DNS-Propagation laufen, sobald die Action die Images des aktuellen Commits veröffentlicht hat:

WATERMAPS_REGISTRY_USERNAME=kevin_janssen \
WATERMAPS_REGISTRY_TOKEN='<read-only-package-token>' \
  ./deploy/scripts/upload-and-deploy.sh \
  --identity ~/.ssh/watermaps_hetzner_ed25519

Der Registry-Token wird nur an docker login --password-stdin übertragen und nicht Teil der Projektkonfiguration. Das Skript überträgt ausschließlich die Deployment-Dateien. Der Server zieht die commitgenauen Images, fixiert deren Digests und lädt beim ersten Start die Geofabrik-Extrakte auf das persistente Volume. Vor dem SSL-Livegang liefert Port 80 außer ACME-Challenges nur 404.

Erst wenn der DNS-A-Record propagiert ist, wird HTTPS mit dem finalen manuellen Befehl aktiviert:

./deploy/scripts/remote-go-live.sh \
  --identity ~/.ssh/watermaps_hetzner_ed25519

Das Skript prüft DNS, beide Länder im Routingindex sowie Testrouten, fordert das Zertifikat an und schaltet anschließend dauerhaft auf HTTPS um. Ausführliche Hinweise stehen in infra/opentofu/README.md und deploy/README.md.

Datenstatus

Die freie Datenstrategie ist bewusst als Fahr- und Planungshilfe umgesetzt. Die App zeigt Attribution und den Status Nicht amtlich, weil freie Karten-/Modelldaten keine amtlich zugelassene Seekarte ersetzen.

Routingstatus

POST /api/routes kann Fahrwasserdaten aus PostGIS, dem lokalen Geofabrik-Dateiindex und wenn explizit aktiviert live aus Overpass zusammenführen. Die Produktionskonfiguration verwendet ausschließlich den lokalen Deutschland-/Niederlande-Index; sie benötigt weder PostGIS noch eine laufende Overpass-Verbindung. Berücksichtigt werden unter anderem navigation_line, recommended_track, fairway, navigierbare Kanäle und explizit für Boote oder Schiffe freigegebene Flüsse. Gesperrte, private, stillgelegte oder im Bau befindliche Wege werden ausgeschlossen.

Wenn freie Laufzeitdaten fehlen, stehen zwei klar als nicht amtlich markierte Fallback-Korridore bereit:

  • Emden Außenhafen → Borkum Reede
  • Emden Außenhafen → Ems/Dortmund-Ems-Kanal → Datteln → Datteln-Hamm-Kanal → Wasserwanderrastplatz Hamm-Innenstadt (rund 153 sm)

Der EmdenHamm-Fallback besitzt keine belastbaren Tiefen- oder Schleusenzeitdaten und ist bewusst auf Sportboote bis 2,5 m Tiefgang begrenzt. Vor der Fahrt sind aktuelle Sperrungen, Betriebszeiten, Wasserstände und amtliche Karten zu prüfen. Kostenfreie Inland-ENCs für den Dortmund-Ems- und Datteln-Hamm-Kanal stellt ELWIS bereit.

Wenn kein Graph passt, liefert die API bewusst 422 no_fairway_route, damit keine irreführende Luftlinie als Bootsroute gezeichnet wird. alternatives im Ergebnis enthält bis zu zwei weitere, topologisch unterschiedliche Optionen.

Kursassistent entlang einer Route

Nach erfolgreicher Routenplanung erscheint „Kursassistent starten“. Der Assistent verwendet den bereits vorhandenen hochgenauen GPS-Datenstrom und berechnet bei jedem neuen Fix einen geschwindigkeits- und genauigkeitsabhängigen Vorausschaupunkt auf der Route. Daraus entstehen Sollkurs über Grund, Kurskorrektur gegenüber dem GPS-Kurs über Grund (COG), Querabstand, Routenfortschritt, Reststrecke und der nächste deutliche Backbord-/Steuerbord-Kurswechsel. Vor engen Richtungswechseln endet die Vorausschau am Kurvenpunkt, damit nicht diagonal über das Fahrwasser abgekürzt wird.

Der Fortschritt wird gegen GPS-Sprünge und sich kreuzende Routenabschnitte stabilisiert. Bei einem mehr als 15 Sekunden alten oder zu ungenauen Fix pausiert die Steueranweisung. Der Gerätekompass bleibt als gekennzeichnete Orientierung sichtbar, wird aber nicht mit dem geografischen Sollkurs verrechnet; eine Kurskorrektur wird erst aus einem belastbaren GPS-COG gebildet. Laut W3C-Geolocation-Spezifikation kann der Browser Position, Genauigkeit, Geschwindigkeit und einen Kurs relativ zu geografisch Nord liefern, garantiert aber nicht die tatsächliche Position des Geräts.

Der Kursassistent steuert weder Ruder noch Maschine und gibt keine NMEA-Kommandos aus. Er ist eine nicht amtliche Navigationshilfe; Ausguck, sichere Geschwindigkeit, Tonnen, Ufer, Verkehr, Wasserstände und amtliche Unterlagen haben immer Vorrang. Browser und Betriebssystem können GPS-Aktualisierungen bei gesperrtem Display oder im Hintergrund anhalten.

Ankerwache mit Tide und Leinenreserve

Die Ankerwache ist unabhängig von einer geplanten Route über das Ankersymbol rechts auf der Karte erreichbar. Sie startet nie automatisch:

  1. Live-GPS starten und genau beim Erreichen des Grundes „Anker gefallen Position jetzt setzen“ wählen. Der Fix muss jünger als zehn Sekunden und auf höchstens 30 m genau sein. Der gespeicherte Ankerpunkt bleibt danach fest.
  2. Tiefe beim Setzen, Höhe der Bugrolle über Wasser, ausgesteckte Ketten-/Leinenlänge, gewünschtes Verhältnis, zusätzliche Wasserstandsreserve, Alarmradius und Tidenzeitraum prüfen.
  3. Erst „Wache starten“ schaltet Positionsalarm, Warnton, Vibration, optionale Browser-Mitteilungen und soweit unterstützt eine Bildschirm-Wachhalteanforderung ein.

Kursassistent, separater Kursalarm und Ankerwache laufen nicht parallel. Beim Öffnen der Ankerfunktion wird eine laufende Kursführung beendet; die geplante Route selbst bleibt erhalten.

Die Leinenplanung verwendet:

(Tiefe beim Setzen + Bugrollenhöhe + maximaler weiterer Tidenanstieg + Wasserstandsreserve) × gewähltes Verhältnis

Die BSH-Pegelhöhe wird dabei ausdrücklich nicht als örtliche Wassertiefe verwendet. Aus der Kurve wird nur die relative Änderung gegenüber dem Zeitpunkt des Ankersetzens abgeleitet. Station und Entfernung bleiben sichtbar. Deckt die Prognose den gewählten Zeitraum nicht vollständig ab, zeigt Watermaps nur den tideunabhängigen Mindestbedarf und bestätigt weder Bedarf noch Reserve. Die laufende Positionswache bleibt trotzdem nutzbar. Die Differenz aus höchstem und niedrigstem Kurvenwert im Zeitraum wird als Tidenhub angezeigt; allgemein bezeichnet „tidal range“ die Höhendifferenz zwischen Hoch- und Niedrigwasser (NOAA).

Das Verhältnis ist absichtlich einstellbar. Die RYA nennt als Orientierung viermal die maximale Wassertiefe bei Kette beziehungsweise sechsmal bei einer Kombination aus Kette und Leine, weist aber zugleich auf Grund und Schwojbereich hin (RYA Anchoring with care). Wind, Wellen, Strom, Schwell, Ankerbauart, Grund, Bootslänge und nahe Gefahren können mehr Länge oder einen enger gewählten Alarmbereich erfordern; die Rechnung entscheidet das nicht selbst.

Auf der Karte erscheinen der feste Ankerpunkt, ein geodätisch in Metern berechneter Alarmring und die Verbindung zum Boot. Ein Driftalarm wird erst ausgelöst, wenn der Abstand auch nach Abzug der gemeldeten GPS-Ungenauigkeit außerhalb des Radius liegt. Umgekehrt werden ein mehr als 20 Sekunden alter Fix, GPS-Ausfall oder eine Genauigkeit schlechter als 30 m als eigener Alarmzustand angezeigt. Das vermindert Fehlalarme, kann eine echte Drift aber auch später melden. Peilmarken, Ankerkontrolle und Ausguck bleiben deshalb erforderlich.

Web-Apps können keine ununterbrochene Hintergrundüberwachung garantieren. iOS, der Browser oder ein gesperrtes Display können GPS, JavaScript, Vibration, Ton und Mitteilungen anhalten. Für eine Nachtwache muss Watermaps sichtbar bleiben; die Funktion ersetzt keinen eigenständigen zugelassenen Ankeralarm.

Reise-, Zeit- und Live-Datenplanung

Eine Route kann bis zu 25 Zwischenziele und eine ISO-Abfahrtszeit enthalten. Die Grund-ETA beginnt an dieser Abfahrtszeit. Für Start, Mitte und Ziel fragt die Web-App die Prognose zum geschätzten Passierzeitpunkt ab. Die Open-Meteo-Marine-Daten enthalten dabei Wellen und modellierte Strömung; die Strömungs-Komponente längs zum jeweiligen Routenkurs wird als klar gekennzeichnete Modellkorrektur der ETA dargestellt. Werte außerhalb des verfügbaren Vorhersagefensters werden nicht als aktuelle Prognose ausgegeben.

Für Start und Ziel werden passende BSH-Tidenstationen zur geplanten Zeit abgefragt. Die Stationsentfernung wird angezeigt, weil Bezugsnull und lokale Abweichungen für die Navigation entscheidend bleiben.

GET /api/navigation/live bindet aktuelle Wasserstände über die dokumentierte PEGELONLINE REST-API v2 ein. Ergebnisse werden 60 Sekunden frisch gehalten; bei Ausfall kann höchstens sechs Stunden lang der letzte erfolgreiche Stand mit dem Status stale angezeigt werden. Für die EmdenHamm-Route werden EMS, DEK und DHK abgefragt.

ELWIS veröffentlicht Schleuseninformationen und Nachrichten für die Binnenschifffahrt. Da dafür keine verlässlich dokumentierte öffentliche REST-/JSON-Schnittstelle vorliegt, wird kein vermeintlicher Live-Status aus HTML gescrapt. Das Backend besitzt stattdessen eine streng auf offizielle WSV-/ELWIS-HTTPS-Quellen begrenzte Adapter-Schnittstelle. Ohne konfigurierten amtlichen Feed zeigt die App den offiziellen Prüf-Link. Der einstellbare Schleusenpuffer ist ausdrücklich nur eine eigene Planannahme, keine gemessene Wartezeit.

Die Etappenplanung wählt nur Häfen innerhalb des Tageslimits und des erlaubten Abstechers. Ausstattungsmerkmale ohne bestätigten Wert gelten sicherheitshalber als unbekannt und erfüllen keinen aktivierten Versorgungsfilter.

Offline gespeichert werden Route, Wegpunkte, Bootsprofil und Abfahrtszeit auf dem jeweiligen Gerät. Live-GPS-Positionen werden weder gespeichert noch übertragen. Der Service Worker hält nur tatsächlich besuchte OpenFreeMap-/OpenSeaMap-Ressourcen zeitlich und mengenmäßig begrenzt vor; Watermaps lädt nicht automatisch ganze Routenkorridore herunter.

Für produktivere Daten kann scripts/import-geofabrik.sh aus einem Geofabrik-PBF routbare Fahrwasser in marine_fairway_edges importieren. Das ist der richtige Weg für "alle Fahrwasserdaten" im eigenen Backend; Rasterkacheln der Karte werden nicht zurückdigitalisiert.

Die Küsten-PBFs lassen sich reproduzierbar von Geofabrik laden und ohne lokal installierte GIS-Tools importieren:

./scripts/download-geofabrik.sh
docker compose --profile postgis up -d postgres redis martin
DATABASE_URL=postgres://seacompass:seacompass@localhost:55432/seacompass \
  ./scripts/import-geofabrik-docker.sh \
    data/geofabrik/germany-latest.osm.pbf \
    data/geofabrik/netherlands-latest.osm.pbf

Ohne Argumente lädt download-geofabrik.sh die vollständigen Extrakte für Deutschland und die Niederlande. Das benötigt mehrere Gigabyte Speicher und Downloadvolumen. Für den EmdenHamm-Korridor genügen gezielt:

./scripts/download-geofabrik.sh niedersachsen nordrhein-westfalen
./scripts/import-geofabrik-docker.sh \
  data/geofabrik/niedersachsen-latest.osm.pbf \
  data/geofabrik/nordrhein-westfalen-latest.osm.pbf

Die vollständigen Niederlande lassen sich separat laden und importieren:

./scripts/download-geofabrik.sh netherlands
DATABASE_URL=postgres://seacompass:seacompass@localhost:55432/seacompass \
  ./scripts/import-geofabrik-docker.sh data/geofabrik/netherlands-latest.osm.pbf

Der Import erkennt auch Schleusen, Häfen, Marinas und Ports und aktualisiert geänderte OSM-Kontaktdaten per Upsert. Für Schleusen werden unter anderem lock=yes, waterway=lock_gate, water=lock, obstacle=lock und entsprechende Seamark-Gates berücksichtigt. Flächen aus überlappenden Extrakten werden über ihre kanonische OSM-ID zusammengeführt. Nach einem Update der Importlogik sollte der bestehende Datenbestand erneut importiert werden.

Deutsche Schleusen können zusätzlich aus dem offiziellen EuRIS-Datenangebot abgeglichen werden. Ein Trockenlauf prüft den Abruf, ohne die Datenbank zu verändern:

DATABASE_URL=postgres://seacompass:seacompass@localhost:55432/seacompass \
EURIS_COUNTRIES=DE EURIS_DRY_RUN=true \
  npm run sync:euris-locks

Zum Speichern EURIS_DRY_RUN=false setzen. EURIS_DETAIL_LIMIT ist optional und wegen der API-Belastung auf 20 Detailaufrufe pro Lauf begrenzt; die kompakten Schleusen- und RIS-Index-Daten werden unabhängig davon vollständig seitenweise gelesen. Ein optionales Zugriffstoken kann über EURIS_API_TOKEN gesetzt werden.

Fehlende Kontakte können zunächst aus den bereits in OSM oder EuRIS verlinkten Facility-Websites ergänzt werden. Dieser erste Adapter verwendet keine Suchmaschine, ist standardmäßig ein Trockenlauf und verarbeitet standardmäßig höchstens 25 Datensätze:

DATABASE_URL=postgres://seacompass:seacompass@localhost:55432/seacompass \
  npm run enrich:marine-websites

Erst nach Prüfung der Zusammenfassung wird das Schreiben explizit aktiviert:

DATABASE_URL=postgres://seacompass:seacompass@localhost:55432/seacompass \
MARINE_WEBSITE_DRY_RUN=false \
  npm run enrich:marine-websites

Die Ergänzungen werden mit derselben Geometrie separat als Quelle facility-website gespeichert. Abgerufen werden ausschließlich öffentliche HTTP(S)-Ziele; private und lokale IP-Bereiche sowie unsichere Redirects werden blockiert. Extrahiert werden strukturierte JSON-LD-Kontakte und explizite tel:-/mailto:-Links, keine frei im Seitentext vermuteten Telefonnummern.

Für benannte Anlagen, denen danach weiterhin Website- oder Kontaktdaten fehlen, gibt es einen konservativen Suchmaschinen-Fallback. Er ist ebenfalls standardmäßig ein Trockenlauf:

DATABASE_URL=postgres://seacompass:seacompass@localhost:55432/seacompass \
MARINE_SEARCH_PROVIDER=duckduckgo \
  npm run enrich:marine-search

Zum kontrollierten Speichern eines kleinen Batches:

DATABASE_URL=postgres://seacompass:seacompass@localhost:55432/seacompass \
MARINE_SEARCH_PROVIDER=duckduckgo \
MARINE_SEARCH_DRY_RUN=false \
MARINE_SEARCH_LIMIT=10 \
  npm run enrich:marine-search

Die Routine lehnt generische Namen wie Hafen oder Schleuse ab, bewertet Anlagenname, Ort, Wasserstraße, Typ und Domain und verlangt einen deutlichen Abstand zum zweitbesten Host. Ein Suchsnippet wird niemals als Kontaktquelle verwendet: Der Ziel-Link wird erneut durch die SSRF-, DNS-, Redirect-, TLS-, Größen- und Timeout-Prüfungen geschickt. Erst wenn auch die Zielseite eindeutig zur Anlage passt, werden dort vorhandene JSON-LD-Daten sowie tel:-/mailto:-Links übernommen. Eine verifizierte offizielle Website kann auch ohne weitere Kontaktfelder ergänzt werden; bestehende OSM-, EuRIS- und frühere Anreicherungswerte werden nicht überschrieben.

DuckDuckGo dokumentiert seine HTML- und Lite-Seiten als Non-JavaScript-Suche, jedoch nicht als stabile allgemeine Such-API. Deshalb läuft dieser Provider mit Parallelität 1, standardmäßig fünf Sekunden Abstand und einem Circuit Breaker: HTTP 202/403/429 oder eine Bot-Prüfung stoppen den Batch, statt fälschlich „keine Treffer“ zu speichern. Als zuverlässigere optionale API kann Brave Web Search verwendet werden:

DATABASE_URL=postgres://seacompass:seacompass@localhost:55432/seacompass \
MARINE_SEARCH_PROVIDER=brave \
BRAVE_SEARCH_API_KEY=... \
MARINE_SEARCH_DRY_RUN=false \
  npm run enrich:marine-search

Im Schreibmodus führt marine_enrichment_attempts je Provider und Suchfingerabdruck einen Checkpoint. Erfolgreiche, mehrdeutige, kontaktlose und fehlgeschlagene Versuche werden mit unterschiedlichen Wiederholungsfristen gespeichert, sodass aufeinanderfolgende Batches fortschreiten, anstatt dieselben Anlagen sofort erneut abzufragen. Die eigentliche Kartenanreicherung bleibt für die bestehende Zusammenführung unter der Datenquelle facility-website; Properties wie enrichmentSource=facility-search, Provider, Suchabfrage, Treffer-URL, Scores und feldweise Provenienz machen den Ursprung auditierbar.

Die Karten-API vereinigt nahe OSM-, EuRIS- und Website-Objekte anhand offizieller Kennungen, normalisierter Anlagennamen, Entfernung und Objektrolle zu einer kanonischen Anlage. Rohdaten bleiben für spätere Neuberechnungen erhalten. Schleusen- und Hafenobjekte werden erst ab Zoom 12 geladen und in einer geclusterten MapLibre-GeoJSON-Ebene GPU-beschleunigt gezeichnet; beim Verschieben wird nur nach moveend neu geladen und die vorherige Anfrage abgebrochen. Erst beim Heranzoomen erscheinen einzelne Info-Symbole. Die streckenbezogene Etappen- und Schleusenplanung bleibt davon unabhängig verfügbar.

Um die Kartenantwort klein zu halten, liefert die API bei Brücken nur Einträge mit bekannter Durchfahrtshöhe oder einem beweglichen Brückentyp aus.

Der lokale PostGIS-Container nutzt standardmäßig Host-Port 55432, damit er nicht mit bestehenden lokalen Postgres-Installationen auf 5432 kollidiert. Setze deshalb für API und Import DATABASE_URL=postgres://seacompass:seacompass@localhost:55432/seacompass.

Lokale Infrastruktur

docker compose --profile postgis up -d postgres redis martin

Danach .env aus .env.example ableiten und für echte PostGIS-Features WATERMAPS_DEMO_DATA=false setzen. Die frühere Variable SEA_COMPASS_DEMO_DATA wird übergangsweise weiterhin akzeptiert.

Dateibasiertes Deutschland-/Niederlande-Routing

Wenn Docker/PostGIS nicht verfügbar ist, kann die API den vollständigen Geofabrik-Extrakt beider Länder als kompakte lokale Fahrwasserdatei verwenden:

npm run setup:local-routing

Der Aufbau liest beide PBFs in Streaming-Durchläufen, führt überlappende OSM-Wege zusammen und erzeugt data/local/germany-netherlands-fairways.json. Für einen ausschließlich lokalen Betrieb:

DATABASE_URL=
REDIS_URL=
WATERMAPS_LOCAL_FAIRWAYS_PATH=data/local/germany-netherlands-fairways.json
WATERMAPS_LIVE_FAIRWAYS=false

Damit benötigen Routen innerhalb des heruntergeladenen Datenstands weder PostGIS noch eine laufende Overpass-Verbindung. Nach einem neuen Geofabrik-Snapshot prüft npm run setup:local-routing die Prüfsummen und baut den Index bei Bedarf atomar neu.

APIs

  • GET /api/config
  • GET /api/weather/marine?lat=54.18&lon=12.09
  • GET /api/weather/marine?lat=54.18&lon=12.09&at=2026-07-20T08:00:00.000Z
  • GET /api/tides/nearest?lat=54.18&lon=12.09&at=2026-07-20T08:00:00.000Z
  • GET /api/navigation/live?waterways=EMS,DEK,DHK
  • GET /api/features?bbox=12,54,13,55&layers=seamarks,bridges,locks,harbours
  • POST /api/routes
S
Description
No description provided
Readme
1.3 MiB
Languages
TypeScript 69.5%
JavaScript 11.4%
Shell 10.4%
CSS 5.9%
Python 1.5%
Other 1.3%