elpatron 90ffff0da6 fix(beta-flyer): update feature descriptions for clarity and accuracy
Revised the descriptions of offline capabilities and encryption methods in the beta flyer to enhance clarity. The PWA is now described as functioning on any smartphone and tablet, and the encryption method is specified as end-to-end.
2026-05-30 14:23:58 +02:00
2026-05-30 14:21:30 +02:00

Kapteins Daagbok

Digitales Yacht-Logbuch als Progressive Web App (PWA) — kostenlos, werbefrei, offline-fähig, End-to-End-verschlüsselt und mit Passkey-Anmeldung.

Live: kapteins-daagbok.eu

Überblick

Kapteins Daagbok richtet sich an private Skipper und Yachtbesitzer, die ihr Bordlogbuch digital führen möchten. Die App speichert Schiffsdaten, Crew-Profile und Reisetage (Törns) in einem Format, das an übliche nautische Logbuch-Vorlagen angelehnt ist.

Alle sensiblen Inhalte werden clientseitig verschlüsselt (Web Crypto API). Der Server sieht nur ciphertext — eine Zero-Knowledge-Architektur. Daten liegen zusätzlich lokal in IndexedDB (Dexie.js) und synchronisieren im Hintergrund, sodass die App auch offline auf See nutzbar ist.

Funktionen

  • Passkey-Authentifizierung (WebAuthn) mit optionaler Recovery-Phrase und lokalem PIN-Fallback
  • Mehrere Logbücher pro Benutzerkonto — eigene Logbücher und per Einladung geteilte Logbücher (Crew-Zugang) klar getrennt
  • Reisetage mit Hafen, Wetter, Tankständen, Ereignissen und Tagesnummer
  • GPS-Tracks (GPX/KML/GeoJSON-Upload, Karte, Statistiken)
  • Foto-Anhänge pro Reisetag
  • Passkey-Signaturen für Skipper und Crew (hybride elektronische Signatur)
  • Schiffsdaten und Crew-Profile (Skipper + Mitglieder)
  • Statistik-Dashboard — Strecken, Verbrauch, Segel/Motor, Hafenkette (pro Logbuch oder accountweit)
  • Kollaboration — Crew per Einladungslink einladen (Schreib- oder Lesezugriff)
  • Push-Benachrichtigungen (optional) — Logbuch-Eigner per Web Push informieren, wenn Crew Änderungen synchronisiert (ohne Klartext-Inhalte; Opt-in in den Einstellungen)
  • Read-only-Freigabe — öffentlicher Lese-Link für Dritte
  • Export — PDF pro Reisetag, CSV-Download/-Teilen
  • Backup & Wiederherstellung — vollständiges verschlüsseltes Logbuch-Backup (Einträge, Fotos, GPS, Crew, Schiff) als .daagbok.json; Restore auf gleichem oder neuem Account
  • PWA — installierbar auf iOS/Android, Offline-Modus, Update-Hinweise
  • Mehrsprachig — Deutsch und Englisch
  • Demo-Logbuch & Onboarding-Tour für neue Nutzer

Architektur

┌─────────────────┐     HTTPS/API        ┌─────────────────┐
│  React PWA      │ ◄──────────────────► │  Express API    │
│  Vite + Dexie   │   (nur ciphertext)   │  Prisma + PG    │
│  IndexedDB      │                      │  PostgreSQL     │
└─────────────────┘                      └─────────────────┘
Schicht Technologie
Frontend React 19, TypeScript, Vite, vite-plugin-pwa
Lokaler Speicher Dexie.js (IndexedDB), Hintergrund-Sync
Backend Node.js, Express, Prisma
Datenbank PostgreSQL 16
Auth WebAuthn (Passkeys) + signiertes HttpOnly-Session-Cookie (daagbok_session)
Krypto Web Crypto API (AES-GCM), BIP39 Recovery
Push (optional) Web Push (VAPID), Custom Service Worker (injectManifest)

Rollen & Zugriff

Rolle Bedeutung
Owner Logbuch angelegt; voller Zugriff, Einladungen, Backup, Löschen; optional Push bei Crew-Änderungen
Collaborator (WRITE) Per Einladung; Einträge bearbeiten und als Crew signieren
Collaborator (READ) Nur Lesen (z. B. öffentlicher Share-Link)

Skipper- und Crew-Profile im Logbuch sind Inhaltsdaten (verschlüsselt), nicht an den Account gebunden. Ein Account kann gleichzeitig Owner eines eigenen und Collaborator in fremden Logbüchern sein.

Authentifizierung & Session

Schicht Verhalten
Login WebAuthn (/api/auth/login-verify) — danach HttpOnly-Cookie, 7 Tage gültig
API-Aufrufe Cookie credentials: 'include' (Client: apiFetch) — kein X-User-Id
Master-Key Nur im RAM; nach Reload Entsperren per Passkey oder lokalem PIN
Step-up Konto löschen, PRF-Enrollment: frische Passkey-Bestätigung (/api/auth/reauth-*)
Sync WRITE Server lehnt Schreib-Sync für Collaborator mit READ ab

Öffentliche Routen (ohne Session): Registrierung/Login-Optionen, Einladungsdetails, Read-only-Share (share-pull), Health-Check, VAPID-Public-Key.

Backup & Wiederherstellung

Nur der Logbuch-Eigner kann unter Einstellungen → Backup & Wiederherstellung ein vollständiges Backup erstellen:

  1. Backup-Passphrase wählen (min. 8 Zeichen, getrennt von der Datei aufbewahren)
  2. Download als .daagbok.json — enthält alle verschlüsselten Payloads inkl. Fotos und GPS-Tracks
  3. Wiederherstellen in einem beliebigen Account (nach Registrierung/Login): Datei + Passphrase

Vor dem Löschen eines Logbuchs weist die App auf diese Funktion hin. Crew-Einladungen und Passkey-Signaturen werden nicht mitübertragen — Inhalte bleiben lesbar, Signaturen auf neuem Account ggf. nicht mehr verifizierbar.

Push-Benachrichtigungen (optional)

Logbuch-Eigner können unter Einstellungen Web Push aktivieren. Sobald ein eingeladenes Crewmitglied mit Schreibrechten (WRITE) Änderungen synchronisiert, erhält der Owner eine generische Benachrichtigung — der Server kennt keine Logbuch-Inhalte (Zero-Knowledge).

Aspekt Verhalten
Auslöser Erfolgreicher Sync-Push durch Collaborator (create/update)
Aggregation Mehrere Änderungen in einem Sync → eine Benachrichtigung pro Logbuch
Drosselung Max. eine Push-Nachricht pro Logbuch alle 3 Minuten
Klick Öffnet die App auf dem betroffenen Logbuch

Voraussetzungen:

  • HTTPS (Produktion)
  • VAPID-Schlüssel auf dem Server (VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY, VAPID_SUBJECT)
  • Browser-Berechtigung „Benachrichtigungen“; auf iOS installierte PWA ab iOS 16.4+

Schlüssel erzeugen: npx web-push generate-vapid-keys (im server/-Verzeichnis oder global).

Ausführlicher Implementierungs- und Testplan: docs/push-notifications-plan.md.

Projektstruktur

kapteins-daagbok/
├── client/              # React-PWA (Frontend)
│   ├── src/
│   │   ├── components/  # UI-Komponenten
│   │   ├── services/    # Auth, Sync, Krypto, Backup, Push, Analytics, …
│   │   ├── sw.ts        # Service Worker (Precache + Web Push)
│   │   └── i18n/        # DE/EN-Übersetzungen
│   └── Dockerfile       # Nginx-Produktions-Image
├── server/              # Express-API + Prisma
│   ├── src/routes/      # auth, logbooks, sync, collaboration, sign, push
│   ├── src/services/    # z. B. pushNotify (Web Push)
│   └── prisma/          # Datenbankschema
├── docs/                # Projektdokumentation
├── scripts/             # Dev- und Deploy-Skripte
├── docker-compose.yml   # Produktions-Stack (DB + Backend + Frontend)
└── VERSION              # App-Version (Build & Footer)

Voraussetzungen

  • Node.js 20+
  • npm
  • Docker (für PostgreSQL in der Entwicklung oder den vollständigen Stack)
  • Optional: eigener OpenWeatherMap-API-Key in den Einstellungen (sonst serverseitiger Key aus .env)
  • Optional: VAPID-Schlüssel für Web Push (siehe Abschnitt Push-Benachrichtigungen)

Lokale Entwicklung

1. Abhängigkeiten installieren

cd server && npm ci && cd ..
cd client && npm ci && cd ..

2. Umgebungsvariablen

cp .env.example .env

Kopiere .env.example nach .env und passe mindestens an:

Variable Dev (Vite) Produktion
RP_ID localhost kapteins-daagbok.eu
ORIGIN http://localhost:5173 https://kapteins-daagbok.eu
SESSION_SECRET empfohlen (≥ 32 Zeichen) Pflicht

ORIGIN muss exakt der Frontend-URL entsprechen (CORS + Session-Cookie). Das Backend lädt .env aus dem Projektroot und optional server/.env.

DATABASE_URL="postgresql://postgres:postgres@localhost:5432/daagbox?schema=public"
OpenWeatherMapAPIKey=          # Fallback für Wetter-Abruf, wenn Nutzer keinen eigenen Key hat
RP_ID=localhost
ORIGIN=http://localhost:5173
SESSION_SECRET=                 # openssl rand -base64 48 (in Prod Pflicht)
# Optional — Web Push (npx web-push generate-vapid-keys)
VAPID_PUBLIC_KEY=
VAPID_PRIVATE_KEY=
VAPID_SUBJECT=mailto:support@kapteins-daagbok.eu

./scripts/start-dev.sh prüft ORIGIN und SESSION_SECRET beim Start und gibt Hinweise aus.

3. Datenbank & Schema

Das Dev-Skript startet PostgreSQL in Docker (postgres-daagbox). Schema anwenden:

cd server && npx prisma db push && cd ..

4. Dev-Server starten

./scripts/start-dev.sh
Dienst URL
Frontend (Vite) http://localhost:5173
Backend API http://localhost:5000
Health Check http://localhost:5000/api/health

Docker (produktionsnah)

Gesamten Stack lokal bauen und starten:

./scripts/start-dev-docker.sh

Frontend: http://localhost · API: http://localhost/api/health

Umgebungsvariablen in .env setzen — mindestens RP_ID, ORIGIN (z. B. http://localhost) und SESSION_SECRET. Für Push die VAPID-Variablen an den Backend-Container durchreichen (docker-compose.ymlbackend.environment).

Deployment

Produktions-Update auf den Server (konfigurierbar via Umgebungsvariablen):

./scripts/update-prod.sh

Standard-Ziel: root@10.0.0.25:/opt/kapteins-daagbok — per REMOTE_HOST, REMOTE_USER, REMOTE_DIR überschreibbar.

Auf dem Server müssen server/.env (oder gleichwertige Umgebung) u. a. DATABASE_URL, RP_ID, ORIGIN, SESSION_SECRET (≥ 32 Zeichen) und bei Push VAPID_* enthalten. Nach Schema-Änderungen: npx prisma db push im Backend-Container.

Dokumentation

Dokument Inhalt
docs/plausible-events.md Custom Events für Plausible Analytics
docs/push-notifications-plan.md Web Push: Architektur, API, Testplan
docs/marketing/kapteins-daagbok-beta-flyer.pdf Beta-Flyer (DIN A4) zum Ausdrucken — Quelle: docs/marketing/beta-flyer.html, neu erzeugen: cd client && npm run generate:flyer
.planning/PROJECT.md Produktvision und Anforderungen (GSD)

Analytics

Die App nutzt Plausible Analytics (self-hosted) für anonyme Nutzungsmetriken — ohne Cookies und ohne personenbezogene Daten in Event-Properties. Details und Goal-Namen: docs/plausible-events.md.

Version

Aktuelle Version: siehe VERSION (wird im App-Footer und beim Docker-Build eingebunden).


© 2026 KnorrLabs/Markus F.J. Busche · kapteins-daagbok.eu

S
Description
No description provided
Readme 54 MiB
Languages
TypeScript 87.2%
CSS 8.8%
JavaScript 1.9%
Shell 1.7%
HTML 0.2%
Other 0.2%