Remove the leftover file content layer and align the docs

This commit is contained in:
tleininger committed 2026-09-23 15:30:53 +02:00
1 parent 3fd3796d73
commit 47d9841532
21 files changed
+154 -327

No files matched your search

+39 -24
View File
@@ -2,7 +2,8 @@
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.
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.
@@ -11,7 +12,7 @@ nachlesen, bevor eine davon in Frage gestellt wird.
| Thema | Datei |
|---|---|
| Warum SSR statt WASM, warum keine DB (AE-1 bis AE-4) | `docs/architektur.md` |
| 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` |
@@ -26,28 +27,36 @@ Sub-Issues als Checkliste im Body, alle am Milestone „Elternbeirat-Website".
## Kommandos
```bash
dotnet run --project Elternbeirat.Web # lokal; Inhalte werden beim Start gelesen (kein Auto-Reload)
dotnet test # Smoke-Tests: jede Route liefert 200
docker compose build && docker compose up -d
# 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
```
Es gibt keine Datenbank, keine Migrationen, kein Seeding. Ein `git clone` ist der
vollständige Stand.
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 im Image**, nicht in einem Volume. Jede Textänderung braucht
Commit und Rebuild. Das ist Absicht (`docs/architektur.md`, AE-3) — nicht
„vereinfachen".
- **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 = Markdown in `Content/pages/`. Neuer Beitrag = Markdown in
`Content/posts/`. Neuer Termin = Eintrag in `Content/events.yml`. In allen
Fällen wird **kein** `.razor` angefasst.
- 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
@@ -57,22 +66,28 @@ vollständige Stand.
- **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`).
- **Keine Datenbank, kein EF Core, kein ORM.** Inhalte sind Dateien.
- **Inhalte gehören nach `Content/`**, nicht als Markup in Komponenten.
- Kein CMS, kein Login, keine Benutzerkonten.
- **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. Bestand: `Markdig`, `YamlDotNet`.
- 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.
- Services über DI, als Singleton registriert (Inhalte werden beim Start
eingelesen und gecacht).
- Öffentliche Typen und Methoden der `Services` bekommen XML-Doc (auf Englisch,
leicht verständlich), Razor-Markup nicht.
- 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, Markdown-Inhalte,
Frontmatter-Schlüssel wie `titel:` sowie Slugs/Dateinamen unter `Content/`
(z. B. `vorstandsteam`, `/termine`).
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`).