# Redaktion Wie die sichtbaren Inhalte der Website gepflegt werden. Der Inhalt liegt in **PocketBase** — einem kleinen Server mit eigenem Admin-Login — und wird dort über die Weboberfläche bearbeitet. Keine Dateien, kein Commit, kein Rebuild: eine Änderung im Admin ist sofort live. > **Stand.** Die Blazor-App liest ihren gesamten Inhalt aus PocketBase (Issue #8); > die alte Datei-Schicht unter `Content/` gibt es nicht mehr. PocketBase ist damit > die einzige Quelle und dieser Abschnitt der einzige Pflegeweg. > **Sprachkonvention.** Feldnamen und Slugs sind **englisch** (`title`, `slug`, > `board`, `posts`). Der Text, den ein Besucher liest, bleibt **deutsch** — also > der Wert eines Feldes (`title: Vorstandsteam`) und der Fließtext. Englische > Schlüssel, deutsche Werte. --- ## Anmelden Das Admin heißt „Redaktion Elternbeirat" und ist unter der PocketBase-Adresse erreichbar: - **Lokal:** (Dev-Stack, siehe `entwicklung.md`). - **Auf dem Server:** über die NPM-Subdomain (Login von außen — noch offen, #9). Redakteure sind **Superuser**: jede vertraute Person aus dem Vorstand bekommt einen eigenen Superuser-Zugang (unter *Collections → System → `_superusers`*). Es gibt bewusst keinen eigenen Login und keinen Editor in der Website selbst — gepflegt wird nur im Admin. --- ## Die Inhaltsarten (Collections) Jede Inhaltsart ist eine **Collection**. Ein neuer Eintrag = ein neuer Record in der passenden Collection (Button *New record*). | Collection | Was | Öffentlich sichtbar über | |---|---|---| | `pages` | Feste Seiten (Vorstand, Impressum, Kontakt …) | Slug, z. B. `/board` | | `posts` | Neuigkeiten / Beiträge | `/posts`, neueste zuerst | | `events` | Termine (Kalender) | `/events` und der `.ics`-Feed | | `faq_topics` | Themen der häufigen Fragen (z. B. „Mensa und Mittagessen") | Als aufklappbare Gruppen auf `/faqs` | | `faqs` | Häufige Fragen | Auf `/faqs`, in der Gruppe ihres Themas | Jede Collection hat als **letztes Feld `public`** (ja/nein). Nur Records mit `public = true` erscheinen auf der Website — so lässt sich ein Entwurf anlegen, ohne dass er schon sichtbar ist. ### Was redaktionell geht — und was Code braucht Redaktion arbeitet mit **Daten**, nicht mit Struktur. Konkret: | Was du willst | Geht redaktionell? | Wie | |---|---|---| | Beitrag / Termin / Frage hinzufügen | **Ja** | Neuer Record in `posts` / `events` / `faqs` — erscheint sofort in der jeweiligen Liste | | Neues FAQ-Thema (neue Gruppe auf `/faqs`) | **Ja** | Neuer Record in `faq_topics` (siehe *Häufige Fragen*) | | Neue Textseite | **Ja** | Neuer Record in `pages` (siehe unten) | | Eine Seite mit einer Liste anteasern | **Ja** | Feld `embed` der Seite (`posts`/`events`) | | **Neue Art von Liste** (eigene Seite mit eigener Sortierung/Gruppierung und eigener Adresse, z. B. „Protokolle") | **Nein** | Braucht Entwicklung: neue Collection **plus** Code | Das heißt: **Bestehende Listen lassen sich beliebig erweitern**, aber eine *neue* Listenart entsteht nicht durch Anlegen einer Collection allein. Die drei Listen (`posts`, `events`, `faqs`) sind fest verdrahtet, weil jede eine eigene Darstellung hat — Datum und Sortierung, Kalender/`.ics`, Themen-Gruppierung. Eine weitere solche Ansicht anzulegen ist ein **Entwickler-Task**: eine neue Collection in PocketBase, eine Lesemethode im `PocketBaseClient` und eine eigene Komponente mit ihrer Route (siehe `docs/entwicklung.md`). Das ist Absicht: Inhalte sind Daten, Struktur und Darstellung sind Code. --- ## Seiten (`pages`) Eine Seite hat `title` (Überschrift für Menschen, Umlaute erlaubt), `slug` (die URL, klein und **ohne Umlaute**: `board`, nicht `über-uns`) und `body` (der Text, als **Markdown**). **Eine neue Seite anlegen** — Record in `pages`, dann ist die Adresse `/` sofort live, ohne Code und ohne Rebuild: 1. `title` setzen (Pflicht). 2. `slug` setzen (Pflicht), englisch und ohne Umlaute — z. B. `slug = schulweg` ergibt `/schulweg`. 3. `body` als Markdown schreiben (optional; darf leer bleiben). 4. **`public` anhaken.** Ohne Haken ist die Seite ein Entwurf und erscheint auf der Website als „nicht gefunden" (404) — das ist der häufigste Stolperstein. 5. Optional `location` (`header`/`footer`) **und** `order` setzen, damit die Seite ins Menü kommt; optional `embed` für eingebettete Blöcke (siehe unten). - **Slug bleibt englisch und ohne Umlaute** — `imprint`, `privacy`, `contact`, `board`, `patrons`; erzwungen per Pattern (siehe *Slug-Regel wird erzwungen* unten). Der `title` darf deutsch mit Umlauten sein (`Förderverein`). - **Reservierte Slugs.** `posts`, `events`, `faqs` und `/` (die Startseite `home`) gehören den festen Listen-/Sonderansichten. Eine `pages`-Seite mit einem dieser Slugs wird von der jeweiligen Ansicht verdeckt und **nicht** angezeigt; in der Produktion dienen solche Records nur als Menü-Platzhalter. - **Menü:** Ob eine Seite ins Menü kommt, steht an der Seite selbst — die Felder `location` (`header` oder `footer`) und `order` (Reihenfolge, ab 1). Die App baut Kopf- und Fußnavigation daraus; nichts wird im Markup angefasst. - **Eingebettete Blöcke:** Das Feld `embed` (Mehrfachauswahl aus `posts`/`events`) hängt unter den Text der Seite dynamische Blöcke. So ist die Startseite (`home`) eine normale Seite mit `embed = [posts, events]`. Leeres `embed` = reine Textseite. Die FAQ-Liste ist kein `embed`: `/faqs` ist eine feste Ansicht (siehe *Häufige Fragen*). > **Impressum und Datenschutz** hängen an ihren Slugs (`imprint`, `privacy`). > Diese Slugs nicht ändern — sonst laufen die rechtlich verlinkten Adressen ins > Leere (404). ### Slug-Regel wird erzwungen Ein Slug muss ein sauberes URL-Segment sein: **Kleinbuchstaben, Ziffern und einzelne Bindestriche als Trenner, keine Umlaute** (`ueber-uns`, nicht `Über uns`). Das ist keine Bitte, sondern eine Feldregel: PocketBase weist einen Slug ab, der sie verletzt, und zeigt beim Speichern einen Fehler. Gibst du `Overview` ein, kommst du erst weiter, wenn du `overview` daraus machst. Die Website verlässt sich darauf — sie repariert einen Slug nicht mehr nachträglich. Die Regel steckt als **Pattern** am Feld `slug`. So ist sie gesetzt (einmalig, pro Collection mit einem Slug — `pages` **und** `posts`): 1. Collection öffnen → *Edit collection* (oben rechts) → Feld `slug`. 2. Am Feld auf das **Zahnrad** (Feldoptionen) → **Pattern**. 3. Als Pattern eintragen: `^[a-z0-9]+(-[a-z0-9]+)*$` 4. **Save** (Feld) und **Save** (Collection). Zum Prüfen: `board`, `ueber-uns`, `faq-lunch` werden angenommen; `Overview`, `über-uns`, `my page`, `-x` und `a--b` werden abgewiesen. --- ## Beiträge (`posts`) Ein Beitrag hat `date`, `title`, `body`, `slug` und `public`. Er erscheint unter `/posts` (neueste zuerst) und unter `/posts/`; die neuesten werden auch auf der Startseite als Vorschau angeteasert. - `date` steuert Sortierung und angezeigtes Datum. Anders als bei Terminen zählt hier nur der **Tag** — eine Uhrzeit wird nie angezeigt, und die UTC-Verschiebung aus dem Termine-Hinweis spielt keine Rolle. Trage einfach das Datum ein. - `slug` ist englisch, klein, ohne Umlaute (z. B. `new-sports-hall-opened`) — dieselbe erzwungene Feldregel wie bei Seiten (siehe *Seiten → Slug-Regel wird erzwungen*). --- ## Termine (`events`) Ein Termin hat `start` (Pflicht), `end` (optional, für mehrstündige oder mehrtägige), `title`, `location` (optional), `note` (optional) und `public`. Kein Slug. Die Übersicht `/events` trennt automatisch in kommende und vergangene Termine; die Reihenfolge der Records spielt keine Rolle. Besucher können `/events.ics` in ihrer Kalender-App abonnieren — der Feed entsteht aus denselben Records. > **Trage einfach die Ortszeit ein.** Gib die Uhrzeit ein, die auf der Seite > stehen soll (Europe/Berlin) — z. B. `08:00`. PocketBase speichert intern in UTC > und zeigt dir nach dem Speichern deshalb einen um 1–2 Stunden früheren Wert an > (aus `08:00` wird im Sommer `06:00`). Das ist **kein** Fehler: Die Website > rechnet beim Anzeigen automatisch nach Ortszeit zurück und zeigt wieder `08:00`, > Sommer- und Winterzeit inklusive. Du musst dich um UTC nicht kümmern. --- ## Häufige Fragen (`faq_topics` und `faqs`) Die FAQ-Seite `/faqs` besteht aus zwei Collections: **Themen** (`faq_topics`) und **Fragen** (`faqs`). Jedes Thema erscheint als aufklappbare Gruppe, darin seine Fragen. Eine Frage gehört zu genau einem Thema, das du aus einer Liste **auswählst** — du tippst es nicht als Text ein. ### Themen (`faq_topics`) Ein Thema hat `title`, `slug`, `intro` (optional), `order` und `public`. - `title` ist die Überschrift der Gruppe (z. B. `Mensa und Mittagessen`). - `intro` ist ein kurzer Einleitungstext (Markdown), der beim Aufklappen über den Fragen steht. - `order` legt die Reihenfolge der Gruppen fest (kleinere Zahl zuerst). - `slug` ist englisch, klein, ohne Umlaute (z. B. `lunch`) — dieselbe Regel wie bei Seiten. Er wird derzeit nicht angezeigt, ist aber Pflicht. - **Eine neue Gruppe** = ein neuer Record in `faq_topics`. Danach steht das Thema bei den Fragen zur Auswahl. ### Fragen (`faqs`) Eine Frage hat `question`, `answer` (Markdown), `topic`, `order` und `public`. - `topic`: das Thema aus `faq_topics` auswählen. - `order` legt die Reihenfolge innerhalb des Themas fest (kleinere Zahl zuerst). > **Stolpersteine.** Eine Frage **ohne** `topic` erscheint nirgends auf der > Website. Ist ein Thema nicht `public`, verschwinden auch alle seine Fragen — > egal, ob diese selbst `public` sind. Überschrift und Rahmentext oben auf `/faqs` sind eine eigene Seite in `pages` (Slug `faqs`). --- ## Gestaltungsbausteine Alle Texte (`body` von Seiten und Beiträgen, `intro` und `answer` bei den FAQs) sind **Markdown**. Die Website gestaltet sie automatisch: Zwischenüberschriften (`## …`) bekommen einen grünen Strich, Listen grüne Punkte, Zitate (`> …`) einen farbigen Balken. Darüber hinaus gibt es ein paar **Bausteine**, mit denen du eine Seite selbst gestaltest — ohne Code und ohne HTML. > **Kein HTML.** HTML im Text (`
`, `
`, `