Die SvelteKit-App liegt unter frontend/, das Backend unter backend/ als eigenständige PocketBase-Instanz mit Dockerfile, docker-compose und versioniertem Schema. - PocketBase-URL über PUBLIC_PB_URL konfigurierbar, Default bleibt die produktive Instanz https://api.stammtisch-hersbruck.de - Schema als Snapshot-Migration der sechs fachlichen Collections (users, teams, events, runs, riders, times), abgezogen von der produktiven Instanz. Verifiziert: ein Erststart gegen leere pb_data legt alle sechs an, Felder und API-Rules stimmen überein. - pb_data und pb_migrations als Bind-Mounts, damit Daten persistieren und im Admin-UI erzeugte Migrationen im Repo landen - Veraltete Dokumentation entfernt: pocketbase_schema.json nannte Collections (stages, results, organizers), die es nicht gibt Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
8.3 KiB
Repo-Umbau auf frontend/ und backend/
Datum: 2026-08-06 Status: Entwurf, vom Nutzer freigegeben
Ziel
Das Repository so umbauen, dass die SvelteKit-App unter frontend/ und eine
eigenständige, lokal lauffähige PocketBase-Instanz unter backend/ liegt —
nach dem Vorbild von therapiezentrum-fortschritt-landingpage.
Anders als beim Vorbild bleibt dies ein Monorepo: Das vorhandene .git im
Root bleibt bestehen, frontend/ und backend/ sind Unterverzeichnisse ohne
eigene Repos.
Ausgangslage
- SvelteKit 5 mit Svelte-5-Runes, PocketBase als Backend
- App liegt direkt im Repo-Root (
src/,static/,scripts/, Configs) - Git-Repo existiert, Branch
master, noch kein Commit — alles untracked - PocketBase läuft ausschließlich remote unter
https://api.stammtisch-hersbruck.de - Die URL ist in
src/lib/stores/pocketbase.svelte.ts:4hartkodiert - Schema-Pflege bisher über
scripts/migrate-schema.tsper Superuser-Token - Es gibt kein
pb_migrations, keinpb_hooks, kein Dockerfile
Befund zum vorhandenen Schema
Der Live-Abruf über GET /api/collections liefert die fachlichen Collections
users, riders, times, events, runs, teams (plus System-Collections
_superusers, _externalAuths, _mfas, _otps, _authOrigins).
Die Datei pocketbase_schema.json im Root nennt dagegen zusätzlich stages,
organizers und results, die live nicht existieren. Sie ist damit
nachweislich veraltet. Maßgeblich ist der Live-Stand — er deckt sich mit den
vorhandenen Stores unter src/lib/stores/.
Zielstruktur
stammtisch-hersbruck.de/ ← .git bleibt hier (Monorepo)
├── CLAUDE.md
├── README.md
├── .gitignore
├── docs/superpowers/{specs,plans}/
├── frontend/
│ ├── src/ static/ scripts/
│ ├── package.json package-lock.json .npmrc
│ ├── svelte.config.js vite.config.ts tsconfig.json
│ ├── components.json
│ ├── .env .env.example .gitignore
│ └── README.md
└── backend/
├── Dockerfile docker-compose.yaml entrypoint.sh
├── .env.example .gitignore README.md
├── pb_migrations/
│ └── <ts>_init_schema.js
├── pb_hooks/ (leer, .gitkeep)
└── pb_data/ (gitignored, entsteht beim ersten Start)
Umsetzung
1. Frontend verschieben
Alle App-Dateien nach frontend/ verschieben:
src/, static/, scripts/, package.json, package-lock.json, .npmrc,
svelte.config.js, vite.config.ts, tsconfig.json, components.json, .env.
node_modules/ und .svelte-kit/ werden nicht verschoben, sondern gelöscht
und in frontend/ per npm ci neu erzeugt — verschobene node_modules
enthalten absolute Pfade in Binaries und Caches.
Keine Config braucht eine Pfadanpassung: Alle Pfade in svelte.config.js,
vite.config.ts und tsconfig.json sind relativ zum jeweiligen Projekt-Root.
Die Scripts unter scripts/ lesen .env relativ zum Arbeitsverzeichnis und
laufen über npm-Scripts, also aus frontend/ heraus — sie funktionieren
unverändert.
2. PocketBase-URL konfigurierbar machen
src/lib/stores/pocketbase.svelte.ts verwendet statt der hartkodierten URL:
import { PUBLIC_PB_URL } from '$env/static/public'
export const api = new PocketBase(PUBLIC_PB_URL) as TypedPocketBase
In frontend/.env und frontend/.env.example:
PUBLIC_PB_URL=https://api.stammtisch-hersbruck.de
Der Default bleibt damit die Remote-Instanz — nichts am bisherigen Verhalten
ändert sich. Für Arbeit gegen das lokale Backend wird die Variable auf
http://127.0.0.1:8090 gesetzt.
Die bestehenden Variablen PB_TYPEGEN_URL, PB_TYPEGEN_TOKEN und
PB_SUPERUSER_TOKEN bleiben unverändert in .env (Typgenerierung und
Migrations-Scripts).
3. Backend aufsetzen
Übernommen aus dem Vorbild, projektspezifisch angepasst:
Dockerfile — Alpine-Basis, PocketBase über Build-Arg PB_VERSION
gepinnt, kopiert pb_migrations/ und pb_hooks/, startet über entrypoint.sh
mit serve --http=0.0.0.0:8090 --dir=/pb/pb_data.
docker-compose.yaml — Volume ./pb_data:/pb/pb_data für Persistenz,
restart: unless-stopped, Healthcheck gegen /api/health, Port 8090.
Env: SUPERUSER_EMAIL, SUPERUSER_PASSWORD, PB_VERSION.
Die TZF-spezifischen Notify-Variablen (TZF_NOTIFY_EMAIL*,
TZF_DASHBOARD_URL) entfallen — dieses Projekt hat keine Mail-Hooks.
entrypoint.sh — legt den Superuser über superuser create an, bewusst
nicht upsert: Existiert der Account schon, scheitert create mit
„must be unique" und ein im Admin-UI geändertes Passwort überlebt jeden
Redeploy. Ohne gesetzte Variablen wird der Schritt übersprungen und PocketBase
gibt seinen Installer-Link im Log aus. Da PocketBase auch im Fehlerfall
Exitcode 0 liefert, wird die Ausgabe ausgewertet, nicht der Status.
.gitignore — pb_data/, *.db, .env, .env.* (Ausnahme
.env.example).
README.md — lokaler Start, Schema-Verwaltung, Persistenz-Hinweise,
Superuser-Verhalten, Update der PocketBase-Version.
4. Schema-Migration erzeugen
Aus dem Live-Export entsteht eine Snapshot-Migration
backend/pb_migrations/<timestamp>_init_schema.js nach dem PocketBase-Muster:
migrate((app) => {
app.importCollections(JSON.stringify([ /* Collections */ ]), false)
}, (app) => { /* down: Collections wieder entfernen */ })
Enthalten sind die sechs fachlichen Collections users, teams, riders, events, runs, times mit ihren Feldern, API-Rules und Indizes. System-Collections
(_superusers, _mfas, _otps, _externalAuths, _authOrigins) bleiben
außen vor — PocketBase legt sie selbst an.
importCollections mit deleteMissing = false, damit die Migration nichts
löscht, was nicht im Snapshot steht.
Ergebnis: Ein frisch gestarteter Container hat dasselbe Schema wie die Live-Instanz, ohne deren Daten.
Die Migration wird nicht gegen die Live-Instanz angewendet — sie beschreibt nur den Zustand, den ein neuer Container herstellen soll.
5. Altlasten entfernen
Gelöscht werden (alle untracked, also unwiederbringlich):
pocketbase_schema.json— veraltet (siehe Befund oben), abgelöst durch die Migrationexample_pb_schema.json— Beispieldatei ohne Bezug zum Projektpocketbase_migrate.zip— altespb_datavon 2023 inkl. Bilddaten, gehört nicht ins Repo
IMPLEMENTATION_SUMMARY.md, POCKETBASE_SCHEMA.md, README_SETUP.md und
UML_basic.png bleiben zunächst im Root erhalten.
6. Root-Dateien anpassen
.gitignoreim Root: ergänzt umfrontend/node_modules/,frontend/.svelte-kit/,frontend/build/,backend/pb_data/,.env,.env.*mit Ausnahme.env.example. Wichtig:frontend/.enventhältPB_SUPERUSER_TOKENund darf nicht in den Commit gelangen — das wird vor dem Commit übergit statusgeprüft.CLAUDE.md: Pfadangaben auf die neue Struktur umstellen (Dev-Commands laufen ausfrontend/), Abschnitt zum Backend ergänzenREADME.mdim Root: kurze Übersicht beider Teile
7. Erster Commit
Das Repo hat noch keinen Commit. Die fertige Struktur wird als initialer Commit angelegt — der Umbau erscheint damit nicht als Verschiebung in der Historie, sondern die Struktur steht von Anfang an richtig da.
Kein git push — der bleibt ausdrücklicher Anweisung vorbehalten.
Verifikation
Der Umbau gilt als erfolgreich, wenn:
cd frontend && npm cifehlerfrei durchläuftcd frontend && npm run checkohne neue Fehler durchläuft (Vergleich gegen den Stand vor dem Umbau — bestehende Fehler zählen nicht als Regression)cd frontend && npm run devstartet und die App unterhttp://stammtisch-hersbruck.de.localhost:31337lädt und Daten von der Remote-Instanz zeigtcd backend && docker compose up -d --buildstartet undcurl http://127.0.0.1:8090/api/healthantwortet- Im lokalen Admin-UI sind die sechs Collections mit ihren Feldern vorhanden
Punkt 4 und 5 setzen ein lauffähiges Docker voraus; ist das nicht verfügbar, wird das ausdrücklich als ungeprüft berichtet statt als erledigt.
Bewusst nicht Teil dieses Umbaus
- Keine Änderung an der Live-Instanz oder deren Daten
- Keine Datenmigration ins lokale Backend
- Kein Deployment-Setup (Coolify o. ä.)
- Keine
pb_hooks— das Verzeichnis wird leer angelegt - Kein Ablösen von
scripts/migrate-schema.ts; das Script bleibt vorerst unverändert im Frontend