stammtisch-hersbruck/backend
Daniel Michelberger 4fa0de8753 feat: Logo pro Team, auch als Wasserzeichen im Seitenhintergrund
teams.logo nimmt eine Datei auf; hochgeladen wird sie in den
Team-Einstellungen. Ohne eigenes Logo bleibt das Wappen aus static/ als
Rueckfalloption - fuer den Stammtisch Hersbruck aendert sich damit nichts,
fuer jedes weitere Team waere es fremdes Vereinswappen gewesen.

Dasselbe Logo liegt gedreht und sehr blass in der rechten unteren Ecke der
Seite. Es haengt fest im Bildschirm, faengt keine Klicks ab und ist fuer
Screenreader nicht vorhanden; im Dunkelmodus etwas kraeftiger, sonst
verschwaende es im dunklen Grund.

In TODO.md ausserdem der Plan fuer Ausfahrten: Sie werden kein zweites
Konzept neben Events, sondern Schalter daran - timing, participation
(offen/bestaetigung/geschlossen) und Serien, die echte Einzeltermine
erzeugen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014dh9W1i7aLSdPYJzQPid5o
2026-09-02 15:42:04 +02:00
..
pb_hooks chore: Repo-Struktur mit frontend/ und backend/ aufsetzen 2026-08-06 13:16:43 +02:00
pb_migrations feat: Logo pro Team, auch als Wasserzeichen im Seitenhintergrund 2026-09-02 15:42:04 +02:00
.env.example chore: PocketBase auf 0.39.11 aktualisieren 2026-08-14 15:52:00 +02:00
.gitignore chore: Repo-Struktur mit frontend/ und backend/ aufsetzen 2026-08-06 13:16:43 +02:00
docker-compose.yaml chore: PocketBase auf 0.39.11 aktualisieren 2026-08-14 15:52:00 +02:00
Dockerfile chore: PocketBase auf 0.39.11 aktualisieren 2026-08-14 15:52:00 +02:00
entrypoint.sh chore: Repo-Struktur mit frontend/ und backend/ aufsetzen 2026-08-06 13:16:43 +02:00
README.md fix: pb_migrations nicht mounten — Deployment startete ohne Collections 2026-08-06 14:06:30 +02:00

stammtisch-hersbruck.de — Backend (PocketBase)

PocketBase-Instanz für Events, Läufe, Fahrer, Zeiten und Teams.

Lokal starten

.env aus der Vorlage anlegen (die .env selbst steht in .gitignore):

cp .env.example .env

und die Werte eintragen — .env.example beschreibt jede Variable. Dann:

docker compose up -d --build

Admin-UI: http://127.0.0.1:8090/_/ — Login mit SUPERUSER_EMAIL/SUPERUSER_PASSWORD.

Damit das Frontend gegen diese Instanz läuft, in ../frontend/.env PUBLIC_PB_URL=http://127.0.0.1:8090 setzen.

Schema

Das Schema liegt als versionierte Migration in pb_migrations/ und wird beim Start automatisch angewendet. Es enthält die sechs fachlichen Collections users, teams, events, runs, riders, times.

1754400000_init_schema.js ist ein Snapshot der produktiven Instanz. Er wurde per GET /api/collections abgezogen und ruft importCollections mit deleteMissing = false auf — die Migration legt an und aktualisiert, löscht aber nichts, was nicht im Snapshot steht.

Schema-Änderungen aus dem Admin-UI holen

pb_migrations/ wird nicht in den Container gemountet — die Migrationen kommen über COPY ins Image (siehe Dockerfile). Das ist Absicht: Ein Bind-Mount überdeckt das Image-Verzeichnis, und auf einem Deployment-Host ohne ausgechecktes Repo legt Docker dort ein leeres Verzeichnis an. PocketBase findet dann keine Migration und startet mit einer Datenbank ohne Collections.

Die Kehrseite: Eine im Admin-UI erzeugte Migration liegt zunächst nur im Container und muss von Hand herausgeholt werden:

# Welche Dateien sind dazugekommen?
docker compose exec pocketbase ls /pb/pb_migrations

# Die neue Datei ins Repo kopieren und committen
docker compose cp pocketbase:/pb/pb_migrations/<datei> ./pb_migrations/

Ohne diesen Schritt ist die Änderung beim nächsten --build verloren.

Ein frisch gestarteter Container hat damit dasselbe Schema wie die produktive Instanz — aber keine Daten.

Datenpersistenz

Sämtliche Laufzeitdaten liegen in der SQLite-DB unter /pb/pb_data: Datensätze, Uploads, die SMTP-Einstellungen und der Superuser. Ohne gemountetes Volume auf diesem Pfad sind sie nach jedem Redeploy verloren.

Das Volume-Mapping ./pb_data:/pb/pb_data steht in der docker-compose.yaml, damit die Persistenz-Konfiguration versioniert im Repo liegt.

Trügerisches Signal: Die Collections kommen aus der Migration und sind nach einem Redeploy auch dann da, wenn gar kein Volume existiert. Sie taugen nicht als Nachweis funktionierender Persistenz — das zeigt nur ein Datensatz, der in keiner Migration steht.

Mount prüfen:

docker inspect <container> --format '{{json .Mounts}}' | jq

Erscheint dort kein Eintrag mit "Destination": "/pb/pb_data", fehlt die Persistenz.

pb_data/ steht in .gitignore und gehört dort auch hin.

Superuser-Verhalten

entrypoint.sh ruft superuser create auf — bewusst nicht upsert. Existiert der Account bereits, scheitert create mit „Value must be unique" und das Passwort bleibt unangetastet. Eine im Admin-UI vorgenommene Passwortänderung überlebt damit jeden Redeploy.

Situation Verhalten
Erster Start, Variablen gesetzt Superuser wird angelegt
Neustart, Account existiert „Superuser existiert bereits — Passwort bleibt unverändert"
Passwort im UI geändert, dann Neustart UI-Passwort gilt weiter, Env wird ignoriert
Variablen nicht gesetzt Übersprungen, PocketBase gibt Installer-Link im Log aus
Passwort zu kurz (< 8 Zeichen) Container bricht mit Exitcode 1 ab

Passwort später ändern: im Admin-UI, nicht über die Env — eine Änderung der Env-Variable hat keine Wirkung mehr, sobald der Account existiert.

PocketBase aktualisieren

Die Version ist über das Build-Arg PB_VERSION gepinnt (Dockerfile und docker-compose.yaml). Wert hochsetzen, committen, neu bauen.

Ein latest gibt es bewusst nicht: Der GitHub-Asset heißt pocketbase_<version>_linux_amd64.zip, enthält die Version also im Dateinamen. Der Pin ist auch gewollt — sonst zieht jeder Rebuild unangekündigt eine neue Version, inklusive möglicher DB-Schema-Migrationen.

Vor einem Update: Changelog prüfen (https://github.com/pocketbase/pocketbase/releases) und pb_data sichern — PocketBase migriert die DB beim Start automatisch, ein Downgrade ist danach nicht mehr ohne Weiteres möglich.