60e5ef6844
All-in-One docker-compose-Stack (Muster von RAPPORT-SERVER gespiegelt): db/auth/rest/kong + cms-Service (Node-API + Hugo-Binary 0.161.1 + Admin-SPA). - DB-backed: posts-Tabelle kanonisch, MD ist generiertes Artefakt - echte Hugo-Vorschau via draft:true + --buildDrafts → /_preview - Publish: DB → content/library/<section>/<slug>.md → hugo build → live - Bild-Upload nach static/images/, Supabase-Auth schützt /api/* - Proxmox-LXC-Script: legt Container an, generiert Secrets, startet Stack Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
99 lines
4.3 KiB
Markdown
99 lines
4.3 KiB
Markdown
# OPENBUREAU CMS
|
|
|
|
Headless CMS vor der Hugo-Engine. Hugo bleibt die Render-Engine; dieser Stack
|
|
schreibt Content aus Supabase in `content/*.md`, baut die Site und serviert sie.
|
|
|
|
## Architektur
|
|
|
|
**Ein** docker-compose-Stack / ein LXC (Muster gespiegelt von RAPPORT-SERVER):
|
|
|
|
```
|
|
docker compose
|
|
├── db supabase/postgres ← posts-Tabelle (schema.sql)
|
|
├── auth gotrue ← Login
|
|
├── rest postgrest ← supabase-js liest/schreibt posts
|
|
├── kong :8000 ← API-Gateway (/auth/v1, /rest/v1)
|
|
└── cms :8080 Node + Hugo-Binary + Admin-SPA
|
|
├─ / live (public/)
|
|
├─ /_preview Vorschau (preview/, --buildDrafts)
|
|
├─ /admin React-Editor
|
|
└─ /api Backend (mountet Repo unter /site)
|
|
```
|
|
|
|
- **cms** hält das Hugo-Binary (0.161.1 extended, = lokal), mountet das Repo-Root
|
|
unter `/site`, serviert die Site selbst (kein separater nginx).
|
|
- Server-seitig spricht `cms` Supabase intern über `http://kong:8000` (Service-Key);
|
|
die Admin-SPA nutzt browser-seitig `API_EXTERNAL_URL` + `ANON_KEY`.
|
|
- **Abweichung von RAPPORT:** `realtime` + `storage` weggelassen (nutzt das CMS
|
|
nicht — Bild-Uploads gehen auf Platte nach `static/images/`). Nachrüstbar durch
|
|
Kopieren der Service-Blöcke aus RAPPORT-SERVER.
|
|
|
|
## Quelle der Wahrheit (DB-backed)
|
|
|
|
Die `posts`-Tabelle in Supabase ist kanonisch. `content/*.md` ist ein
|
|
**generiertes Artefakt** — nicht von Hand editieren, wird beim Publish
|
|
überschrieben. Drafts liegen als `draft: true` in `content/` und werden vom
|
|
Live-Build automatisch ausgelassen; nur der Preview-Build (`--buildDrafts`)
|
|
zeigt sie.
|
|
|
|
## Setup
|
|
|
|
### Schnellweg: Proxmox-LXC
|
|
|
|
`proxmox/create-openbureau-lxc.sh` auf dem Proxmox-Host ausführen — legt den LXC
|
|
an, installiert Docker, zieht das Repo, generiert alle Secrets und startet den
|
|
Stack. Details im Script-Kopf (Storage, Bridge, GIT_TOKEN für das private Repo).
|
|
|
|
### Manuell (oder im Container)
|
|
|
|
1. `cp .env.example .env`
|
|
2. `POSTGRES_PASSWORD` + `JWT_SECRET` setzen: je `openssl rand -hex 32`
|
|
3. Keys ableiten: `node scripts/generate-keys.mjs` → `ANON_KEY` + `SERVICE_ROLE_KEY` in `.env`
|
|
4. `SITE_URL` + `API_EXTERNAL_URL` auf die LAN-/Domain-Adresse setzen
|
|
5. `docker compose up -d --build` (Erststart: DB bootet + Schema/Migrations)
|
|
6. Login-User anlegen (Self-Signup ist aus):
|
|
```
|
|
source .env
|
|
curl -X POST "$API_EXTERNAL_URL/auth/v1/admin/users" \
|
|
-H "apikey: $SERVICE_ROLE_KEY" -H "Authorization: Bearer $SERVICE_ROLE_KEY" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"email":"du@example.ch","password":"…","email_confirm":true}'
|
|
```
|
|
|
|
Dann: Admin `…:8080/admin/` · Live `…:8080/` · Preview `…:8080/_preview/`
|
|
|
|
### Lokale Entwicklung am Admin
|
|
|
|
`cd admin && npm install && npm run dev` (Vite-Devserver, proxyt `/api` +
|
|
`/_preview` an den laufenden Container auf :8080).
|
|
|
|
## API
|
|
|
|
Alle `/api/*` (ausser `/health`) verlangen `Authorization: Bearer <supabase-token>`.
|
|
|
|
| Methode | Pfad | Zweck |
|
|
|---------|---------------------|----------------------------------------|
|
|
| GET | `/api/health` | Healthcheck (offen) |
|
|
| GET | `/api/posts` | Alle Posts listen |
|
|
| GET | `/api/posts/:id` | Einen Post |
|
|
| POST | `/api/posts` | Post anlegen (Draft) |
|
|
| PUT | `/api/posts/:id` | Post aktualisieren |
|
|
| POST | `/api/preview/:id` | Draft als `draft:true` schreiben + Preview-Build |
|
|
| POST | `/api/publish/:id` | Live schreiben + Public-Build + (opt.) git commit |
|
|
| POST | `/api/upload` | Bild → `static/images/`, liefert `/images/<name>` |
|
|
|
|
## Stand
|
|
|
|
- [x] api + Hugo-Binary, Ein-Container-Setup
|
|
- [x] Publish-Flow (DB → MD → `hugo` → live)
|
|
- [x] Echte Hugo-Vorschau (`--buildDrafts` → `/_preview`)
|
|
- [x] React-Admin (`admin/`) — Login, Editor, Frontmatter-Formular, iframe-Preview
|
|
- [x] Supabase-Auth-Middleware auf der API
|
|
- [x] Bild-Upload für `cover_image`
|
|
|
|
### Noch denkbar
|
|
|
|
- nginx davor für Caching/TLS (oder über deinen bestehenden Reverse-Proxy)
|
|
- Post löschen / Slug-Umbenennung (alte MD-Datei entfernen)
|
|
- Mehrbenutzer + Rollen, wenn ein zweiter Autor dazukommt
|