Heute liegen alle Inhalte als Markdown im Repo und werden ins Image gebacken. Ein neuer Beitrag heisst: auschecken, Markdown anlegen, committen, Image bauen, deployen. Das kann ein Entwickler – aber kein normales Elternbeirats-Mitglied.
Anforderungen
Mehrere Redakteure, regelmaessig, ohne Entwickler.
Sofort live – kein Rebuild/Deploy-Schritt.
Login / Zugriffsschutz.
Persistenz ueber Container-Neustart und Deploy hinaus (kritischste Anforderung) – Inhalte liegen ausserhalb des Images.
Backup und Wiederherstellung durch den Betreiber selbst, ohne Entwickler.
Recherche-Ergebnis (Kurzfassung)
Zentraler Konflikt: "sofort live" (3) und "Inhalte ausserhalb des Images" (4) ziehen gegeneinander. Untersucht:
A – Eigenbau Mini-CMS in Blazor: ausgeschlossen (selbstgebaute Auth = groesste Angriffsflaeche).
B – Git-basiertes UI auf Gitea (Sveltia/Decap): Backup konkurrenzlos (Git-Historie, Restore = git clone), Datenschutz perfekt, keine zweite DB. Haken: "live erst nach Auto-Rebuild", ausser man baut Volume + Webhook.
Fortschritt 2026-09-22 — PocketBase steht (Option C, aber schlank):
Entscheidung gefallen: sofort live ist Pflicht -> kein Git-CMS (B), sondern eine schreibbare Datenschicht. Directus verworfen (Overkill). Genommen: PocketBase (eine Binary, SQLite eingebaut, Admin-UI + Login dabei).
Container auf Unraid: ghcr.io/muchobien/pocketbase:0.40.4 (fester Tag, nicht latest), Daten im Volume /mnt/user/appdata/pocketbase/pb_data, Host-Port 8090.
Collection posts (Base): title, slug, body (Editor/HTML), published (bool), date; Unique-Index auf slug.
API rules getestet: List/View published = true (oeffentlich lesbar), Create/Update/Delete @request.auth.id != "" (nur eingeloggt). Schreiben ohne Login gibt 403.
2 Beispiel-Beitraege eingespielt (aus Content/posts/*.md, noch mit TODO-Platzhaltern).
Naechster Schritt (Sub-Issue #8): In der Blazor-App einen getippten HttpClient-Service bauen, der posts per REST von PocketBase liest, plus Ausfallverhalten (PocketBase down). Danach: NPM-Subdomain fuer den Admin-Login, Backup-Cron auf /pb_data + Restore einmal echt testen (#9), Doku/AE-2/AE-3 nachziehen.
Offene Risiken: PocketBase ist pre-1.0 ("nicht fuer Produktion empfohlen") -> Updates bewusst machen, Changelog lesen. Backup der einen SQLite-Datei ist daher kritisch.
**Fortschritt 2026-09-22 — PocketBase steht (Option C, aber schlank):**
Entscheidung gefallen: **sofort live** ist Pflicht -> kein Git-CMS (B), sondern eine schreibbare Datenschicht. Directus verworfen (Overkill). Genommen: **PocketBase** (eine Binary, SQLite eingebaut, Admin-UI + Login dabei).
- Container auf Unraid: `ghcr.io/muchobien/pocketbase:0.40.4` (fester Tag, nicht latest), Daten im Volume `/mnt/user/appdata/pocketbase/pb_data`, Host-Port 8090.
- Superuser angelegt. Dashboard: `http://<unraid>:8090/_/`.
- Collection `posts` (Base): title, slug, body (Editor/HTML), published (bool), date; Unique-Index auf slug.
- API rules getestet: List/View `published = true` (oeffentlich lesbar), Create/Update/Delete `@request.auth.id != ""` (nur eingeloggt). Schreiben ohne Login gibt 403.
- 2 Beispiel-Beitraege eingespielt (aus Content/posts/*.md, noch mit TODO-Platzhaltern).
**Naechster Schritt (Sub-Issue #8):** In der Blazor-App einen getippten HttpClient-Service bauen, der `posts` per REST von PocketBase liest, plus Ausfallverhalten (PocketBase down). Danach: NPM-Subdomain fuer den Admin-Login, Backup-Cron auf /pb_data + Restore einmal echt testen (#9), Doku/AE-2/AE-3 nachziehen.
**Offene Risiken:** PocketBase ist pre-1.0 ("nicht fuer Produktion empfohlen") -> Updates bewusst machen, Changelog lesen. Backup der einen SQLite-Datei ist daher kritisch.
Update 2026-09-22 — zweite Collection events steht:
Collection events (Base): title (Text, req), start (Date, req), end (Date, opt), location (Text, opt), note (Text, opt). Kein slug/published (Termine sind Liste, keine Einzel-URL).
API rules: List/View offen (leer = öffentlich), Create/Update/Delete @request.auth.id != "". Getestet: Lesen 200 / Schreiben ohne Login 403.
4 Termine aus events.yml eingespielt (Sitzung, Herbstbasar, Weihnachtsferien, Elternsprechtag).
Datum-Fallstrick (wichtig für den Blazor-Service): PocketBase Date-Feld erwartet/liefert das Format YYYY-MM-DD HH:mm:ss.SSSZ. Kurzformen wie 2026-10-08 19:30 werden als leer/ungültig verworfen (400). Ganztägige Termine haben Uhrzeit 00:00:00 — daran erkennt der Service später „ganztägig".
Beide Inhaltstypen (posts, events) sind damit in PocketBase modelliert, befüllt und abgesichert. Nächstes: Blazor-Leseservice (#8).
**Update 2026-09-22 — zweite Collection `events` steht:**
- Collection `events` (Base): `title` (Text, req), `start` (Date, req), `end` (Date, opt), `location` (Text, opt), `note` (Text, opt). Kein slug/published (Termine sind Liste, keine Einzel-URL).
- API rules: List/View offen (leer = öffentlich), Create/Update/Delete `@request.auth.id != ""`. Getestet: Lesen 200 / Schreiben ohne Login 403.
- 4 Termine aus events.yml eingespielt (Sitzung, Herbstbasar, Weihnachtsferien, Elternsprechtag).
**Datum-Fallstrick (wichtig für den Blazor-Service):** PocketBase Date-Feld erwartet/liefert das Format `YYYY-MM-DD HH:mm:ss.SSSZ`. Kurzformen wie `2026-10-08 19:30` werden als leer/ungültig verworfen (400). Ganztägige Termine haben Uhrzeit `00:00:00` — daran erkennt der Service später „ganztägig".
Beide Inhaltstypen (posts, events) sind damit in PocketBase modelliert, befüllt und abgesichert. Nächstes: Blazor-Leseservice (#8).
Collection pages (Base): slug (Text, req, Unique-Index), title (Text, req), body (Editor, req). List/View offen, Create/Update/Delete @request.auth.id != "".
Alle 11 Seiten aus Content/pages/*.md migriert (impressum, datenschutz, kontakt, faq, faq-mensa, faq-schliessfach, faq-elterneuro, faq-elternarbeit, foerderverein, vorstandsteam, downloads). Body als Markdown, doppelte H1 entfernt, TODO-Platzhalter + interne Links (/kontakt usw.) erhalten.
Getestet: Lesen 200 (11 Seiten), Schreiben ohne Login blockiert.
Damit ist der gesamte Content (posts, events, pages) in PocketBase — alle Markdowns + events.yml migriert.
Neuer Arbeitsmodus:.env hat jetzt PB_URL/PB_ADMIN_EMAIL/PB_ADMIN_PASSWORD (gitignored). Damit Login als Superuser -> Collections anlegen + Records schreiben per API, OHNE die API rules zu öffnen (Superuser bypasst sie). Kein „Create kurz offen" mehr nötig. .env.example entsprechend erweitert.
Nächstes (#8): Blazor-Leseservices (posts/events/pages) statt Content/-Dateien; danach die alten Markdowns/events.yml + die dateibasierten Reader entfernen. Dann NPM-Subdomain für Admin-Login + Backup/Restore (#9).
**Update 2026-09-22 — dritte Collection `pages`, Migration komplett:**
- Collection `pages` (Base): `slug` (Text, req, Unique-Index), `title` (Text, req), `body` (Editor, req). List/View offen, Create/Update/Delete `@request.auth.id != ""`.
- Alle **11 Seiten** aus Content/pages/*.md migriert (impressum, datenschutz, kontakt, faq, faq-mensa, faq-schliessfach, faq-elterneuro, faq-elternarbeit, foerderverein, vorstandsteam, downloads). Body als Markdown, doppelte H1 entfernt, TODO-Platzhalter + interne Links (/kontakt usw.) erhalten.
- Getestet: Lesen 200 (11 Seiten), Schreiben ohne Login blockiert.
**Damit ist der gesamte Content (posts, events, pages) in PocketBase — alle Markdowns + events.yml migriert.**
**Neuer Arbeitsmodus:** `.env` hat jetzt PB_URL/PB_ADMIN_EMAIL/PB_ADMIN_PASSWORD (gitignored). Damit Login als Superuser -> Collections anlegen + Records schreiben per API, OHNE die API rules zu öffnen (Superuser bypasst sie). Kein „Create kurz offen" mehr nötig. `.env.example` entsprechend erweitert.
**Nächstes (#8):** Blazor-Leseservices (posts/events/pages) statt Content/-Dateien; danach die alten Markdowns/events.yml + die dateibasierten Reader entfernen. Dann NPM-Subdomain für Admin-Login + Backup/Restore (#9).
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Heute liegen alle Inhalte als Markdown im Repo und werden ins Image gebacken. Ein neuer Beitrag heisst: auschecken, Markdown anlegen, committen, Image bauen, deployen. Das kann ein Entwickler – aber kein normales Elternbeirats-Mitglied.
Anforderungen
Recherche-Ergebnis (Kurzfassung)
Zentraler Konflikt: "sofort live" (3) und "Inhalte ausserhalb des Images" (4) ziehen gegeneinander. Untersucht:
Empfehlung: maximale Einfachheit + bombensicheres Backup -> B; "in Sekunden live" harte Bedingung -> C.
Sub-Issues (Reihenfolge)
Herkunft: tasks/001-redaktion-ohne-entwickler.md
Fortschritt 2026-09-22 — PocketBase steht (Option C, aber schlank):
Entscheidung gefallen: sofort live ist Pflicht -> kein Git-CMS (B), sondern eine schreibbare Datenschicht. Directus verworfen (Overkill). Genommen: PocketBase (eine Binary, SQLite eingebaut, Admin-UI + Login dabei).
ghcr.io/muchobien/pocketbase:0.40.4(fester Tag, nicht latest), Daten im Volume/mnt/user/appdata/pocketbase/pb_data, Host-Port 8090.http://<unraid>:8090/_/.posts(Base): title, slug, body (Editor/HTML), published (bool), date; Unique-Index auf slug.published = true(oeffentlich lesbar), Create/Update/Delete@request.auth.id != ""(nur eingeloggt). Schreiben ohne Login gibt 403.Naechster Schritt (Sub-Issue #8): In der Blazor-App einen getippten HttpClient-Service bauen, der
postsper REST von PocketBase liest, plus Ausfallverhalten (PocketBase down). Danach: NPM-Subdomain fuer den Admin-Login, Backup-Cron auf /pb_data + Restore einmal echt testen (#9), Doku/AE-2/AE-3 nachziehen.Offene Risiken: PocketBase ist pre-1.0 ("nicht fuer Produktion empfohlen") -> Updates bewusst machen, Changelog lesen. Backup der einen SQLite-Datei ist daher kritisch.
Update 2026-09-22 — zweite Collection
eventssteht:events(Base):title(Text, req),start(Date, req),end(Date, opt),location(Text, opt),note(Text, opt). Kein slug/published (Termine sind Liste, keine Einzel-URL).@request.auth.id != "". Getestet: Lesen 200 / Schreiben ohne Login 403.Datum-Fallstrick (wichtig für den Blazor-Service): PocketBase Date-Feld erwartet/liefert das Format
YYYY-MM-DD HH:mm:ss.SSSZ. Kurzformen wie2026-10-08 19:30werden als leer/ungültig verworfen (400). Ganztägige Termine haben Uhrzeit00:00:00— daran erkennt der Service später „ganztägig".Beide Inhaltstypen (posts, events) sind damit in PocketBase modelliert, befüllt und abgesichert. Nächstes: Blazor-Leseservice (#8).
Update 2026-09-22 — dritte Collection
pages, Migration komplett:pages(Base):slug(Text, req, Unique-Index),title(Text, req),body(Editor, req). List/View offen, Create/Update/Delete@request.auth.id != "".Damit ist der gesamte Content (posts, events, pages) in PocketBase — alle Markdowns + events.yml migriert.
Neuer Arbeitsmodus:
.envhat jetzt PB_URL/PB_ADMIN_EMAIL/PB_ADMIN_PASSWORD (gitignored). Damit Login als Superuser -> Collections anlegen + Records schreiben per API, OHNE die API rules zu öffnen (Superuser bypasst sie). Kein „Create kurz offen" mehr nötig..env.exampleentsprechend erweitert.Nächstes (#8): Blazor-Leseservices (posts/events/pages) statt Content/-Dateien; danach die alten Markdowns/events.yml + die dateibasierten Reader entfernen. Dann NPM-Subdomain für Admin-Login + Backup/Restore (#9).