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>
209 lines
8.3 KiB
Markdown
209 lines
8.3 KiB
Markdown
# 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:4` hartkodiert
|
|
- Schema-Pflege bisher über `scripts/migrate-schema.ts` per Superuser-Token
|
|
- Es gibt kein `pb_migrations`, kein `pb_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:
|
|
|
|
```ts
|
|
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:
|
|
|
|
```js
|
|
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 Migration
|
|
- `example_pb_schema.json` — Beispieldatei ohne Bezug zum Projekt
|
|
- `pocketbase_migrate.zip` — altes `pb_data` von 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
|
|
|
|
- **`.gitignore`** im Root: ergänzt um `frontend/node_modules/`,
|
|
`frontend/.svelte-kit/`, `frontend/build/`, `backend/pb_data/`, `.env`,
|
|
`.env.*` mit Ausnahme `.env.example`. Wichtig: `frontend/.env` enthält
|
|
`PB_SUPERUSER_TOKEN` und darf nicht in den Commit gelangen — das wird vor
|
|
dem Commit über `git status` geprüft.
|
|
- **`CLAUDE.md`**: Pfadangaben auf die neue Struktur umstellen
|
|
(Dev-Commands laufen aus `frontend/`), Abschnitt zum Backend ergänzen
|
|
- **`README.md`** im 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:
|
|
|
|
1. `cd frontend && npm ci` fehlerfrei durchläuft
|
|
2. `cd frontend && npm run check` ohne neue Fehler durchläuft (Vergleich gegen
|
|
den Stand vor dem Umbau — bestehende Fehler zählen nicht als Regression)
|
|
3. `cd frontend && npm run dev` startet und die App unter
|
|
`http://stammtisch-hersbruck.de.localhost:31337` lädt und Daten von der
|
|
Remote-Instanz zeigt
|
|
4. `cd backend && docker compose up -d --build` startet und
|
|
`curl http://127.0.0.1:8090/api/health` antwortet
|
|
5. 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
|