Files
Elternbeirat/CLAUDE.md
T

78 lines
3.6 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.
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 keine DB (AE-1 bis AE-4) | `docs/architektur.md` |
| Unraid, compose, NPM-Proxy-Host, Registry, Rollback | `docs/deployment.md` |
| Inhalte anlegen und ändern | `docs/inhalte-pflegen.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
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
```
Es gibt keine Datenbank, keine Migrationen, kein Seeding. Ein `git clone` ist der
vollständige Stand.
## 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".
- **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.
- 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`).
- **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.
- UI-Texte auf Deutsch, ohne Anglizismen. `Termine`, nicht `Events`.
- Neue NuGet-Abhängigkeiten vorher begründen. Bestand: `Markdig`, `YamlDotNet`.
## 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.
- **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`).