160 lines
7.5 KiB
Markdown
160 lines
7.5 KiB
Markdown
# 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:** <http://localhost:8090/_/> (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 |
|
||
| `faqs` | Häufige Fragen | Werden auf der FAQ-Seite gruppiert angezeigt |
|
||
|
||
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 |
|
||
| Neue Textseite | **Ja** | Neuer Record in `pages` (siehe unten) |
|
||
| Eine Seite mit einer Liste anteasern | **Ja** | Feld `embed` der Seite (`posts`/`events`/`faqs`) |
|
||
| **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 `/<slug>`
|
||
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`. 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
|
||
`faqs`/`posts`/`events`) hängt unter den Text der Seite dynamische Blöcke. So
|
||
ist die Startseite (`home`) eine normale Seite mit `embed = [posts, events]`,
|
||
und `/faqs` eine Seite mit `embed = [faqs]`. Leeres `embed` = reine Textseite.
|
||
|
||
> **Impressum und Datenschutz** hängen an ihren Slugs (`imprint`, `privacy`).
|
||
> Diese Slugs nicht ändern — sonst laufen die rechtlich verlinkten Adressen ins
|
||
> Leere (404).
|
||
|
||
---
|
||
|
||
## Beiträge (`posts`)
|
||
|
||
Ein Beitrag hat `date`, `title`, `body`, `slug` und `public`. Er erscheint unter
|
||
`/posts` (neueste zuerst) und unter `/posts/<slug>`; 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`).
|
||
|
||
---
|
||
|
||
## 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 (`faqs`)
|
||
|
||
Eine Frage hat `question`, `answer` (Markdown), `topic` (eines von
|
||
`mensa`/`schliessfach`/`elterneuro`/`elternarbeit`) und `public`. Die App baut
|
||
die FAQ-Seite generiert: sie gruppiert die Fragen nach `topic`. Der Rahmentext
|
||
oben auf `/faqs` ist eine eigene Seite in `pages` (Slug `faqs`).
|
||
|
||
---
|
||
|
||
## Regeln beim Speichern
|
||
|
||
- **Nach dem Ändern einer Zugriffsregel** immer den Haupt-*Save* der Collection
|
||
drücken, sonst greift die Änderung nicht.
|
||
- Die vier Collections sind öffentlich **lesbar** (List/View offen), aber nur
|
||
eingeloggt **schreibbar** — ein Schreibversuch ohne Login wird abgewiesen. Das
|
||
ist Absicht; nicht „vereinfachen".
|
||
- **Backup:** Der gesamte Inhalt liegt in `pb_data`. Ein Backup dieses
|
||
Verzeichnisses (plus Restore-Test) ist der Sicherungsweg — eingerichtet in #9.
|