94 lines
5.1 KiB
Markdown
94 lines
5.1 KiB
Markdown
# CLAUDE.md
|
|
|
|
Website des Elternbeirats der IGMH. Blazor Web App mit statischem
|
|
Server-Side-Rendering, .NET 10. Läuft als Container auf Unraid hinter dem Nginx
|
|
Proxy Manager. Die Inhalte liegen in **PocketBase** (zweiter Container); die App
|
|
liest sie pro Request über einen typisierten `PocketBaseClient`.
|
|
|
|
Architekturentscheidungen und deren Begründung: `docs/architektur.md`. Dort
|
|
nachlesen, bevor eine davon in Frage gestellt wird.
|
|
|
|
## Wann welches Dokument
|
|
|
|
| Thema | Datei |
|
|
|---|---|
|
|
| Warum SSR statt WASM, warum PocketBase als Datenschicht (AE-1 bis AE-4) | `docs/architektur.md` |
|
|
| Stack lokal starten, Tests, compose-Overlays | `docs/entwicklung.md` |
|
|
| Unraid, compose, NPM-Proxy-Host, Registry, Rollback | `docs/deployment.md` |
|
|
| Inhalte anlegen und ändern (PocketBase-Admin) | `docs/redaktion.md` |
|
|
| Impressum, Datenschutz, Fotos | `docs/recht.md` |
|
|
| Offene Arbeit, Meilensteine, offene Punkte | Gitea-Issues (Milestone „Elternbeirat-Website") |
|
|
|
|
Offene Aufgaben liegen als **Gitea-Issues**, nicht als Markdown im Repo. So löst
|
|
das Anlegen oder Ändern eines Tickets keinen Build aus. Die vier Arbeitsstränge
|
|
(Redaktionssystem, Deployment, Inhalte, Infrastruktur) sind Parent-Issues mit
|
|
Sub-Issues als Checkliste im Body, alle am Milestone „Elternbeirat-Website".
|
|
|
|
## Kommandos
|
|
|
|
```bash
|
|
# Lokaler Stack (App + PocketBase) über das Dev-Overlay, siehe docs/entwicklung.md:
|
|
docker compose -f compose.yaml -f compose.dev.yaml up --build # App :5000, PocketBase-Admin :8090/_/
|
|
dotnet test # Smoke-Tests (starten eigene PocketBase) + Unit-Tests
|
|
```
|
|
|
|
Die App liest ihren Inhalt pro Request aus PocketBase; sie hält selbst keinen
|
|
Inhalt und liest nichts beim Start ein. Kein EF Core, keine Migrationen, kein
|
|
Seeding im Code. Ein `git clone` ist **nicht** der vollständige Stand — der
|
|
Inhalt liegt in PocketBase (`pb_data`), das separat gesichert wird (siehe
|
|
`docs/deployment.md`).
|
|
|
|
## Nicht offensichtlich
|
|
|
|
- **Inhalte liegen in PocketBase** (`pb_data`-Volume), nicht im Image. Eine
|
|
Textänderung ist ein Eintrag im PocketBase-Admin und sofort live — kein Commit,
|
|
kein Rebuild (`docs/architektur.md`, AE-2/AE-3). Nur die statischen Assets unter
|
|
`wwwroot/` (CSS, Fonts, PDFs) sind ins Image gebacken.
|
|
- **Kein `UseHttpsRedirection()`, kein `UseHsts()`.** NPM terminiert TLS; beides
|
|
erzeugt hinter dem Proxy eine Redirect-Schleife. `UseForwardedHeaders` mit
|
|
geleerten `KnownNetworks`/`KnownProxies` ist korrekt so, weil der Container kein
|
|
Port-Mapping hat und nur über NPM erreichbar ist.
|
|
- **Das chiseled-Runtime-Image hat keine Shell.** `HEALTHCHECK` mit `curl` oder
|
|
`sh` schlägt dort fehl.
|
|
- Neue Seite / neuer Beitrag / neuer Termin / neue Frage = **Record in der
|
|
passenden PocketBase-Collection** (`pages` / `posts` / `events` / `faqs`), nicht
|
|
eine Datei und **kein** `.razor`. `pages` mit `slug` ist sofort unter `/<slug>`
|
|
erreichbar; `location`+`order` steuern das Menü, `embed` bettet Listen ein
|
|
(`docs/redaktion.md`). Eine **neue Art von Liste** (eigene Route/Logik) ist
|
|
dagegen Code: neue Collection + `PocketBaseClient`-Methode + Komponente
|
|
(`docs/entwicklung.md`).
|
|
- Slugs ohne Umlaute (`ueber-uns`, nicht `über-uns`).
|
|
|
|
## Regeln
|
|
|
|
- **Statisches SSR ist der Default.** Kein `@rendermode` ohne konkreten Anlass,
|
|
und wenn, dann an genau der einen Komponente — nie global.
|
|
- **Keine externen Ressourcen.** Keine CDN-Skripte, keine Google Fonts, keine
|
|
Maps- oder Video-Embeds. Schriften werden selbst ausgeliefert. Grund ist
|
|
Datenschutz, nicht Geschmack (`docs/recht.md`).
|
|
- **Kein EF Core, kein ORM, keine Migrationen.** Inhalte kommen aus PocketBase
|
|
über den `PocketBaseClient` (REST), nicht aus einer relationalen DB im Code.
|
|
- **Inhalte gehören nach PocketBase**, nicht als Markup in Komponenten und nicht
|
|
in Dateien im Repo.
|
|
- Kein eigenes CMS, kein Login und keine Benutzerkonten **in der Website** —
|
|
gepflegt wird ausschließlich im PocketBase-Admin (Redakteure sind Superuser).
|
|
- UI-Texte auf Deutsch, ohne Anglizismen. `Termine`, nicht `Events`.
|
|
- Neue NuGet-Abhängigkeiten vorher begründen. Genutzt wird nur `Markdig`
|
|
(Markdown → HTML). `YamlDotNet` stammt aus der abgelösten Datei-Schicht, wird
|
|
nicht mehr verwendet und soll aus dem `csproj` entfernt werden.
|
|
|
|
## Stil
|
|
|
|
- Nullable aktiviert, `ImplicitUsings` an, File-scoped Namespaces.
|
|
- Datenzugriff über den typisierten `PocketBaseClient` (registriert via
|
|
`AddHttpClient`), der pro Request liest — kein Start-Cache, kein Singleton mit
|
|
Inhalten. Komponenten liegen feature-basiert unter `Features/<Bereich>/`.
|
|
- Öffentliche Typen und Methoden im `PocketBaseClient` und in `Contracts`
|
|
bekommen XML-Doc (auf Englisch, leicht verständlich), Razor-Markup nicht.
|
|
- **Code durchgängig auf Englisch** — Typen, Member, Variablen, Kommentare,
|
|
Skripte und Doku. Das gilt **auch für Domänenbegriffe**: im Code `Event`, nicht
|
|
`Termin`; `Post`, nicht `Beitrag`. Deutsch bleibt ausschließlich, was ein
|
|
Besucher liest oder ein Redakteur pflegt: UI-Texte sowie die **Werte** der
|
|
PocketBase-Records (z. B. `title: Vorstandsteam`, der Markdown-`body`). Die
|
|
Feldnamen und Slugs bleiben dagegen englisch (`title`, `slug`, `/board`).
|