docs: update infrastructure, project status, and frontend docs

Add Multi-Server Orchestration (Phase 1-8) to all docs:
- INFRASTRUCTURE.md: Hetzner 1/2 production servers, SSH infrastructure,
  payload-contracts, deployment workflows, port-forwarding
- PROJECT_STATUS.md: Orchestration changelog, production URLs, SSH commands
- FRONTEND.md: payload-contracts usage, CI/CD pipelines, staging/production
  deploy, work order system, ESLint config, updated tenant IDs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Martin Porwoll 2026-02-15 22:49:38 +00:00
parent 0e978e77f4
commit 9f7a9ad558
3 changed files with 580 additions and 388 deletions

View file

@ -1,6 +1,6 @@
# Infrastruktur Dokumentation # Infrastruktur Dokumentation
*Letzte Aktualisierung: 13. Februar 2026* *Letzte Aktualisierung: 15. Februar 2026*
## Gesamtübersicht ## Gesamtübersicht
@ -21,6 +21,7 @@
│ │ 37.24.237.179 │ cloud.complexcaresolutions.de → 10.10.179.100 │ │ │ │ 37.24.237.179 │ cloud.complexcaresolutions.de → 10.10.179.100 │ │
│ │ 37.24.237.180 │ zh3.de (Nginx PM) → 10.10.180.100 │ │ │ │ 37.24.237.180 │ zh3.de (Nginx PM) → 10.10.180.100 │ │
│ │ 37.24.237.181 │ porwoll.tech (Caddy) → 10.10.181.99 │ │ │ │ 37.24.237.181 │ porwoll.tech (Caddy) → 10.10.181.99 │ │
│ │ │ :2204 → sv-frontend (10.10.181.104:22) [GitHub Actions] │ │
│ │ 37.24.237.182 │ FREI (Reserve) │ │ │ │ 37.24.237.182 │ FREI (Reserve) │ │
│ │ │ │ │ │ │ │
│ └──────────────────────────────────┬──────────────────────────────────────────┘ │ │ └──────────────────────────────────┬──────────────────────────────────────────┘ │
@ -31,15 +32,27 @@
│ └── porwoll.org (intern DNS only) │ │ └── porwoll.org (intern DNS only) │
│ │ │ │
│ HETZNER (Extern) │ │ HETZNER (Extern) │
│ ├── 78.46.87.137 (Hetzner 1 - zweitmeinu.ng) │ ├── 78.46.87.137 (Hetzner 1) — blogwoman.de, ccs.de, zweitmeinu.ng
│ ├── 94.130.141.114 (Hetzner 2 - Porwoll) │ ├── 94.130.141.114 (Hetzner 2) — porwoll.de, caroline-porwoll.*
│ └── 162.55.85.18 (Hetzner 3 - Payload Prod) │ └── 162.55.85.18 (Hetzner 3) — CMS + Analytics (Payload Prod)
│ │ │ │
└─────────────────────────────────────────────────────────────────────────────────────┘ └─────────────────────────────────────────────────────────────────────────────────────┘
``` ```
--- ---
## Server-Übersicht
| Server | IP | Verwaltung | Zweck | Sites |
|--------|-----|-----------|-------|-------|
| **sv-payload** | 10.10.181.100 | LXC (Proxmox) | CMS Development | pl.porwoll.tech |
| **sv-frontend** | 10.10.181.104 | LXC (Proxmox) | Frontend Development | *-dev.porwoll.tech |
| **Hetzner 1** | 78.46.87.137 | Plesk | Frontend Production | blogwoman.de, ccs.de, zweitmeinu.ng |
| **Hetzner 2** | 94.130.141.114 | Plesk | Frontend Production | porwoll.de, caroline-porwoll.* |
| **Hetzner 3** | 162.55.85.18 | Manuell (SSH) | CMS + Analytics Prod | cms.c2sgmbh.de, analytics.c2sgmbh.de |
---
## Öffentliche IP-Adressen ## Öffentliche IP-Adressen
| IP | Verwendung | Ziel (intern) | | IP | Verwendung | Ziel (intern) |
@ -48,6 +61,7 @@
| 37.24.237.179 | cloud.complexcaresolutions.de | 10.10.179.100 (Nextcloud) | | 37.24.237.179 | cloud.complexcaresolutions.de | 10.10.179.100 (Nextcloud) |
| 37.24.237.180 | zh3.de (via Cloudflare) | 10.10.180.100 (Nginx PM) | | 37.24.237.180 | zh3.de (via Cloudflare) | 10.10.180.100 (Nginx PM) |
| 37.24.237.181 | porwoll.tech (Cloudflare) | 10.10.181.99 (Caddy) | | 37.24.237.181 | porwoll.tech (Cloudflare) | 10.10.181.99 (Caddy) |
| 37.24.237.181:2204 | GitHub Actions SSH Deploy | 10.10.181.104:22 (sv-frontend) |
| 37.24.237.182 | FREI (Reserve) | - | | 37.24.237.182 | FREI (Reserve) | - |
--- ---
@ -85,23 +99,23 @@
- Node.js 22.x - Node.js 22.x
- pnpm - pnpm
- Next.js 16.2.0-canary.41 - Next.js 16.2.0-canary.41
- Claude Code (aktuell) - Claude Code 2.1.37
- Codex CLI (aktuell) - Codex CLI (aktuell)
- Gemini CLI (aktuell) - Gemini CLI (aktuell)
### Projekte & Ports ### Projekte & Ports
| Port | Service | Repository | URL | | Port | Service | Repository | Staging URL | Production |
|------|---------|------------|-----| |------|---------|------------|-------------|------------|
| 3000 | frontend-porwoll | frontend.porwoll.de | porwoll-dev.porwoll.tech | | 3000 | frontend-porwoll | frontend.porwoll.de | porwoll-dev.porwoll.tech | **porwoll.de** ✅ |
| 3001 | frontend-blogwoman | frontend.blogwoman.de | blogwoman-dev.porwoll.tech | | 3001 | frontend-blogwoman | frontend.blogwoman.de | blogwoman-dev.porwoll.tech | **blogwoman.de** ✅ |
| 3002 | frontend-caroline-com | frontend.caroline-porwoll.com | caroline-com-dev.porwoll.tech | | 3002 | frontend-caroline-com | frontend.caroline-porwoll.com | caroline-com-dev.porwoll.tech | - |
| 3003 | frontend-caroline-de | frontend.caroline-porwoll.de | caroline-de-dev.porwoll.tech | | 3003 | frontend-caroline-de | frontend.caroline-porwoll.de | caroline-de-dev.porwoll.tech | - |
| 3004 | frontend-ccs | frontend.complexcaresolutions.de | ccs-dev.porwoll.tech | | 3004 | frontend-ccs | frontend.complexcaresolutions.de | ccs-dev.porwoll.tech | - |
| 3005 | frontend-gunshin | frontend.gunshin.de | gunshin-dev.porwoll.tech | | 3005 | frontend-gunshin | frontend.gunshin.de | gunshin-dev.porwoll.tech | - |
| 3006 | frontend-sensual | frontend.sensualmoment.de | sensual-dev.porwoll.tech | | 3006 | frontend-sensual | frontend.sensualmoment.de | sensual-dev.porwoll.tech | - |
| 3007 | frontend-zweitmeinu | frontend.zweitmeinu.ng | zweitmeinu-dev.porwoll.tech | | 3007 | frontend-zweitmeinu | frontend.zweitmeinu.ng | zweitmeinu-dev.porwoll.tech | - |
| 3008 | frontend-zytoskandal | frontend.zytoskandal.de | zytoskandal-dev.porwoll.tech | | 3008 | frontend-zytoskandal | frontend.zytoskandal.de | zytoskandal-dev.porwoll.tech | - |
### Service-Verwaltung ### Service-Verwaltung
@ -136,24 +150,137 @@ systemctl status frontend-*
--- ---
## GitHub Organisation: complexcaresolutions ## SSH-Infrastruktur
| Repository | Beschreibung | Visibility | ### Verbindungen von sv-payload
|------------|--------------|------------|
| cms.c2sgmbh | Payload CMS Backend | Internal | | Ziel | Host-Alias | User | Key | Zweck |
| frontend.porwoll.de | porwoll.de Frontend | Internal | |------|-----------|------|-----|-------|
| frontend.blogwoman.de | blogwoman.de Frontend | Internal | | sv-frontend (10.10.181.104) | `sv-frontend` | frontend | `~/.ssh/frontend_deploy` | Entwicklung, Work Orders |
| frontend.caroline-porwoll.com | caroline-porwoll.com Frontend | Internal | | Hetzner 1 (78.46.87.137) | `hetzner1` | root | `~/.ssh/plesk_deploy` | Production Troubleshooting |
| frontend.caroline-porwoll.de | caroline-porwoll.de Frontend | Internal | | Hetzner 2 (94.130.141.114) | `hetzner2` | root | `~/.ssh/plesk_deploy` | Production Troubleshooting |
| frontend.complexcaresolutions.de | CCS Website Frontend | Internal |
| frontend.gunshin.de | gunshin.de Frontend | Internal | ### SSH-Config (`/home/payload/.ssh/config`)
| frontend.sensualmoment.de | sensualmoment.de Frontend | Internal |
| frontend.zweitmeinu.ng | zweitmeinu.ng Frontend | Internal | ```
| frontend.zytoskandal.de | zytoskandal.de Frontend | Internal | Host sv-frontend frontend
HostName 10.10.181.104
User frontend
IdentityFile ~/.ssh/frontend_deploy
IdentitiesOnly yes
Host hetzner1 plesk1
HostName 78.46.87.137
User root
IdentityFile ~/.ssh/plesk_deploy
IdentitiesOnly yes
StrictHostKeyChecking accept-new
Host hetzner2 plesk2
HostName 94.130.141.114
User root
IdentityFile ~/.ssh/plesk_deploy
IdentitiesOnly yes
StrictHostKeyChecking accept-new
```
### Port-Forwarding (GitHub Actions → sv-frontend)
GitHub Actions kann sv-frontend nicht direkt erreichen (internes Netz). Lösung: UDM Pro SE Port-Forward.
```
GitHub Actions → 37.24.237.181:2204 → UDM Pro SE → 10.10.181.104:22 (sv-frontend)
```
Die SSH-Credentials sind als Repository-Secrets gespeichert (`SSH_HOST`, `SSH_PORT`, `SSH_USER`, `SSH_PRIVATE_KEY`).
--- ---
## Hetzner 3 - Payload Production ## GitHub Organisation: complexcaresolutions
| Repository | Beschreibung | Visibility | Production |
|------------|--------------|------------|------------|
| cms.c2sgmbh | Payload CMS Backend | Internal | cms.c2sgmbh.de |
| **payload-contracts** | **Shared Types + API Client** | **Internal** | — |
| frontend.porwoll.de | porwoll.de Frontend | Internal | **porwoll.de** ✅ |
| frontend.blogwoman.de | blogwoman.de Frontend | Internal | **blogwoman.de** ✅ |
| frontend.caroline-porwoll.com | caroline-porwoll.com Frontend | Internal | - |
| frontend.caroline-porwoll.de | caroline-porwoll.de Frontend | Internal | - |
| frontend.complexcaresolutions.de | CCS Website Frontend | Internal | - |
| frontend.gunshin.de | gunshin.de Frontend | Internal | - |
| frontend.sensualmoment.de | sensualmoment.de Frontend | Internal | - |
| frontend.zweitmeinu.ng | zweitmeinu.ng Frontend | Internal | - |
| frontend.zytoskandal.de | zytoskandal.de Frontend | Internal | - |
### payload-contracts
Shared TypeScript-Package (`@c2s/payload-contracts`) als Git-Dependency für alle Frontends.
```
CMS (payload-cms) Contracts (payload-contracts) Frontends
━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━
payload-types.ts ──extract-types──→ src/types/payload-types.ts
src/types/collections.ts ←──── import { Page, Post }
src/api-client/ ←──── import { createPayloadClient }
src/blocks/registry.tsx ←──── import { createBlockRenderer }
```
---
## Hetzner 1 - Frontend Production (blogwoman.de)
- **IP:** 78.46.87.137
- **Verwaltung:** Plesk
- **SSH:** `ssh hetzner1` (von sv-payload)
- **Web-Server:** nginx-only + Phusion Passenger 6.1.0
- **Node.js:** 22.x
### Sites
| Domain | Status | Repository | Deploy |
|--------|--------|------------|--------|
| blogwoman.de | ✅ Live | frontend.blogwoman.de | GitHub Webhook → Plesk Git Pull |
| complexcaresolutions.de | ⏸️ Geplant | frontend.complexcaresolutions.de | - |
| zweitmeinu.ng | ⏸️ Geplant | frontend.zweitmeinu.ng | - |
### Deployment
- **Methode:** Plesk Git-Integration mit GitHub Webhook
- **Webhook:** `complexcaresolutions.de:8443` (SSL-Cert ist für diese Domain)
- **Branch:** `main` (Push → Auto-Pull → Passenger Restart)
- **Document Root:** `/var/www/vhosts/blogwoman.de/httpdocs/`
### Konfiguration (nginx-only)
Plesk muss auf **nginx-only** (nicht nginx→Apache) konfiguriert sein, da Apache ErrorDocument-Directives Next.js 404-Handling stören und Redirect-Loops verursachen.
---
## Hetzner 2 - Frontend Production (porwoll.de)
- **IP:** 94.130.141.114
- **Verwaltung:** Plesk
- **SSH:** `ssh hetzner2` (von sv-payload)
- **Web-Server:** nginx-only + Phusion Passenger 6.1.0
- **Node.js:** 22.x
### Sites
| Domain | Status | Repository | Deploy |
|--------|--------|------------|--------|
| porwoll.de | ✅ Live | frontend.porwoll.de | GitHub Webhook → Plesk Git Pull |
| caroline-porwoll.com | ⏸️ Geplant | frontend.caroline-porwoll.com | - |
| caroline-porwoll.de | ⏸️ Geplant | frontend.caroline-porwoll.de | - |
### Deployment
- **Methode:** Plesk Git-Integration mit GitHub Webhook
- **Branch:** `main` (Push → Auto-Pull → Passenger Restart)
- **Document Root:** `/var/www/vhosts/porwoll.de/httpdocs/`
---
## Hetzner 3 - CMS + Analytics Production
- **IP:** 162.55.85.18 - **IP:** 162.55.85.18
- **Domain:** cms.c2sgmbh.de - **Domain:** cms.c2sgmbh.de
@ -185,16 +312,58 @@ systemctl status frontend-*
--- ---
## Development Workflow ## Deployment-Workflow
### CMS (Payload)
``` ```
DEVELOPMENT STAGING PRODUCTION sv-payload (develop) → GitHub CI → sv-payload (main) → Hetzner 3 (deploy.sh)
sv-frontend → sv-payload → Hetzner 03
porwoll.tech pl.porwoll.tech cms.c2sgmbh.de
develop branch main branch
``` ```
**AI Tools:** Claude Code, Codex CLI, Gemini CLI, VS Code Remote-SSH ### Frontends
```
sv-frontend (develop) GitHub Plesk (Hetzner 1/2)
━━━━━━━━━━━━━━━━━━━━ ━━━━━━ ━━━━━━━━━━━━━━━━━━━
1. Entwicklung CI: Lint + Build
(Claude Code) ──push──→ ✅ auf develop
2. Staging-Test │
(*-dev.porwoll.tech) │
3. Merge develop → main ──push──→ CI: Lint + Build
✅ auf main
Webhook ─────────→ 4. Plesk Git Pull
5. pnpm install
6. pnpm build
7. Passenger Restart
8. Site live ✅
```
### Staging-Deploy (GitHub Actions)
Push auf `develop` → GitHub Actions → SSH via Port-Forward → `pnpm install && pnpm build` auf sv-frontend.
### Work-Order-Workflow (neue Blocks/Collections)
```
sv-payload sv-frontend
━━━━━━━━━━ ━━━━━━━━━━━
1. CMS Block/Collection ändern
2. pnpm payload generate:types
3. cd ~/payload-contracts && pnpm extract
4. ./scripts/create-work-order.sh "Titel"
5. git commit && git push
6. git pull (payload-contracts)
7. Claude Code mit Work Order starten
8. Block implementieren
9. pnpm build (Verify)
10. git commit && git push
11. Ergebnis verifizieren
12. Work Order → completed/ verschieben
```
--- ---
@ -213,30 +382,46 @@ porwoll.tech pl.porwoll.tech cms.c2sgmbh.de
### Production (Hetzner) ### Production (Hetzner)
| Service | URL | | Service | URL | Server |
|---------|-----| |---------|-----|--------|
| Payload Admin | https://cms.c2sgmbh.de/admin | | Payload Admin | https://cms.c2sgmbh.de/admin | Hetzner 3 |
| Payload API | https://cms.c2sgmbh.de/api | | Payload API | https://cms.c2sgmbh.de/api | Hetzner 3 |
| Umami Analytics | https://analytics.c2sgmbh.de | | Umami Analytics | https://analytics.c2sgmbh.de | Hetzner 3 |
| blogwoman.de | https://blogwoman.de | Hetzner 1 |
| porwoll.de | https://porwoll.de | Hetzner 2 |
--- ---
## Quick Reference ## Quick Reference
```bash ```bash
# Frontend-Server # --- Development ---
ssh frontend@10.10.181.104 ssh frontend@10.10.181.104 # sv-frontend
ssh root@10.10.181.99 # sv-caddy
systemctl reload caddy # Caddy Caddyfile neu laden
# Hetzner 3 Production # --- CMS Production ---
ssh payload@162.55.85.18 ssh payload@162.55.85.18 # Hetzner 3
pm2 logs payload # CMS Logs
# Caddy neu laden # --- Frontend Production ---
ssh root@10.10.181.99 "systemctl reload caddy" ssh hetzner1 # Hetzner 1 (blogwoman.de)
ssh hetzner2 # Hetzner 2 (porwoll.de)
# Frontend Service starten # Git-Status auf Production prüfen
systemctl start frontend-porwoll ssh hetzner1 "cd /var/www/vhosts/blogwoman.de/httpdocs && git log --oneline -3"
ssh hetzner2 "cd /var/www/vhosts/porwoll.de/httpdocs && git log --oneline -3"
# Passenger-Status
ssh hetzner1 "passenger-status"
ssh hetzner2 "passenger-status"
# --- Work Orders ---
cd ~/payload-contracts
./scripts/create-work-order.sh "Titel" --extract
./scripts/execute-work-order.sh work-orders/YYYY-MM-DD-slug.md
``` ```
--- ---
*Dokumentation: Martin Porwoll | Complex Care Solutions GmbH | 13.02.2026* *Dokumentation: Martin Porwoll | Complex Care Solutions GmbH | 15.02.2026*

View file

@ -12,6 +12,8 @@ Die komplette Entwicklungsinfrastruktur ist eingerichtet und funktionsfähig:
- Analytics (Umami) - Analytics (Umami)
- **Community Management System** (YouTube, Facebook, Instagram) - **Community Management System** (YouTube, Facebook, Instagram)
- **YouTube Operations Hub** (Multi-Kanal-Verwaltung) - **YouTube Operations Hub** (Multi-Kanal-Verwaltung)
- **Multi-Server Orchestration** (SSH, Contracts, CI/CD, Plesk Production)
- **2 Production-Sites live:** blogwoman.de + porwoll.de
--- ---
@ -28,7 +30,7 @@ Die komplette Entwicklungsinfrastruktur ist eingerichtet und funktionsfähig:
| 703 | sv-analytics | 10.10.181.103 | Umami Analytics | ✅ Running | | 703 | sv-analytics | 10.10.181.103 | Umami Analytics | ✅ Running |
| 704 | sv-frontend | 10.10.181.104 | Multi-Project Next.js | ✅ Running | | 704 | sv-frontend | 10.10.181.104 | Multi-Project Next.js | ✅ Running |
### Hetzner 3 (Production) ### Hetzner 3 (CMS Production)
- [x] Debian 13 Installation - [x] Debian 13 Installation
- [x] PostgreSQL 17 mit payload_db und umami_db - [x] PostgreSQL 17 mit payload_db und umami_db
@ -41,6 +43,14 @@ Die komplette Entwicklungsinfrastruktur ist eingerichtet und funktionsfähig:
- [x] Backup-Scripts (täglich) - [x] Backup-Scripts (täglich)
- [x] CVE-2025-55182 Hotfix - [x] CVE-2025-55182 Hotfix
### Hetzner 1 + 2 (Frontend Production)
- [x] Hetzner 1 (78.46.87.137): blogwoman.de — Plesk, nginx-only, Passenger 6.1.0, Node 22
- [x] Hetzner 2 (94.130.141.114): porwoll.de — Plesk, nginx-only, Passenger 6.1.0, Node 22
- [x] GitHub Webhooks für Auto-Deploy bei Push auf main
- [x] SSH-Zugriff von sv-payload (root, key: plesk_deploy)
- [x] Env-Vars pro Domain (Tenant-spezifisch)
### Caddy Reverse Proxy (sv-caddy) ### Caddy Reverse Proxy (sv-caddy)
- [x] Caddy 2.9.x mit Cloudflare DNS Plugin - [x] Caddy 2.9.x mit Cloudflare DNS Plugin
@ -124,13 +134,35 @@ Die komplette Entwicklungsinfrastruktur ist eingerichtet und funktionsfähig:
- [x] SSH-Zugriff mit Key - [x] SSH-Zugriff mit Key
- [x] VS Code Remote-SSH kompatibel - [x] VS Code Remote-SSH kompatibel
### Multi-Server Orchestration (Phase 1-8)
- [x] **SSH-Infrastruktur:** sv-payload → sv-frontend, Hetzner 1/2 (root)
- [x] **payload-contracts Repo:** Shared types, API client, block registry
- Type-Extraction aus CMS payload-types.ts
- `createPayloadClient()` mit Tenant-Isolation
- `createBlockRenderer()` mit discriminated unions
- [x] **Work-Order-System:** Git-basierte Koordination CMS → Frontends
- Template + Scripts (`create-work-order.sh`, `execute-work-order.sh`)
- [x] **blogwoman.de Migration:** Contracts-Client + Bridge-Pattern
- [x] **porwoll.de Migration:** Direkte Contracts-Types, 9 Blocks
- [x] **Claude Code auf sv-frontend:** v2.1.37, CLAUDE.md in allen Repos
- [x] **Plesk Production Deployment:**
- Hetzner 1 (78.46.87.137): blogwoman.de — nginx-only + Passenger
- Hetzner 2 (94.130.141.114): porwoll.de — nginx-only + Passenger
- GitHub Webhooks für Auto-Deploy (Push main → Plesk Git Pull → Build)
- [x] **CI/CD GitHub Actions:**
- CI: Lint + Build auf push develop/main
- Staging Deploy: SSH via UDM Pro SE Port-Forward (37.24.237.181:2204)
- Production Deploy: Plesk Git-Integration (Webhook)
### GitHub Repositories ### GitHub Repositories
Organisation: **complexcaresolutions** (Internal) Organisation: **complexcaresolutions** (Public Frontend-Repos)
- [x] cms.c2sgmbh (Payload CMS) - [x] cms.c2sgmbh (Payload CMS) — Internal
- [x] frontend.porwoll.de - [x] payload-contracts (Shared Types + API Client) — Internal
- [x] frontend.blogwoman.de - [x] frontend.porwoll.de — **Live auf porwoll.de**
- [x] frontend.blogwoman.de — **Live auf blogwoman.de**
- [x] frontend.caroline-porwoll.com - [x] frontend.caroline-porwoll.com
- [x] frontend.caroline-porwoll.de - [x] frontend.caroline-porwoll.de
- [x] frontend.complexcaresolutions.de - [x] frontend.complexcaresolutions.de
@ -153,24 +185,34 @@ Organisation: **complexcaresolutions** (Internal)
## 🔜 Nächste Schritte ## 🔜 Nächste Schritte
### Kurzfristig (diese Woche) ### Erledigt
1. [x] ~~Meta (Facebook/Instagram) Kommentar-Synchronisation fertigstellen~~ 1. [x] ~~Meta (Facebook/Instagram) Kommentar-Synchronisation~~
2. [x] ~~YouTube Thumbnail-Download für Offline-Anzeige~~ 2. [x] ~~YouTube Thumbnail-Download~~
3. [x] ~~Monitoring & Alerting Dashboard~~
4. [x] ~~Multi-Server Orchestration (8 Phasen)~~
5. [x] ~~porwoll.de Frontend (Live auf Plesk)~~
6. [x] ~~blogwoman.de Frontend (Live auf Plesk)~~
7. [x] ~~CI/CD Pipelines (GitHub Actions + Plesk Webhooks)~~
### Mittelfristig (Februar/März 2026) ### Kurzfristig
3. [ ] porwoll.de Frontend-Entwicklung 8. [ ] porwoll.de: Fehlende Blocks implementieren (~6 Blocks via Work Orders)
4. [ ] blogwoman.de Frontend mit YouTube-Integration 9. [ ] blogwoman.de: Types-Bridge durch direkte Contracts-Imports ersetzen
5. [ ] Design-System (Tailwind + Shadcn/UI) 10. [ ] blogwoman.de: YouTube-Serien-Integration vervollständigen
6. [ ] Frontend-Staging auf Hetzner 3
### Langfristig (Q1 2026) ### Mittelfristig (März/April 2026)
7. [ ] Alle 9 Frontends entwickeln 11. [ ] complexcaresolutions.de Frontend starten
8. [ ] Migration von Plesk-Domains zu neuer Infra 12. [ ] caroline-porwoll.com/de Frontend starten
9. [ ] AI-gestützte Kommentar-Moderation 13. [ ] Cookie-Banner implementieren (DSGVO)
10. [x] ~~Monitoring & Alerting Dashboard~~ 14. [ ] Weitere Frontends auf Plesk deployen
### Langfristig (Q2 2026)
15. [ ] Alle 9 Frontends entwickeln und deployen
16. [ ] AI-gestützte Kommentar-Moderation
17. [ ] Performance-Optimierung (ISR, Edge Caching)
--- ---
@ -189,10 +231,12 @@ Organisation: **complexcaresolutions** (Internal)
### Production (Hetzner) ### Production (Hetzner)
| Service | URL | Status | | Service | URL | Server | Status |
|---------|-----|--------| |---------|-----|--------|--------|
| Payload CMS | https://cms.c2sgmbh.de | ✅ | | Payload CMS | https://cms.c2sgmbh.de | Hetzner 3 | ✅ |
| Umami Analytics | https://analytics.c2sgmbh.de | ✅ | | Umami Analytics | https://analytics.c2sgmbh.de | Hetzner 3 | ✅ |
| blogwoman.de | https://blogwoman.de | Hetzner 1 | ✅ |
| porwoll.de | https://porwoll.de | Hetzner 2 | ✅ |
--- ---
@ -214,7 +258,7 @@ codex # Codex CLI
gemini # Gemini CLI gemini # Gemini CLI
``` ```
### Hetzner 3 ### Hetzner 3 (CMS Production)
```bash ```bash
# SSH Zugang # SSH Zugang
@ -227,11 +271,36 @@ ssh payload@162.55.85.18
pm2 logs payload pm2 logs payload
``` ```
### Hetzner 1 + 2 (Frontend Production)
```bash
# SSH Zugang (von sv-payload)
ssh hetzner1 # 78.46.87.137 - blogwoman.de
ssh hetzner2 # 94.130.141.114 - porwoll.de
# Logs
ssh hetzner1 "passenger-status"
ssh hetzner2 "passenger-status"
# Git-Status prüfen
ssh hetzner1 "cd /var/www/vhosts/blogwoman.de/httpdocs && git log --oneline -3"
ssh hetzner2 "cd /var/www/vhosts/porwoll.de/httpdocs && git log --oneline -3"
```
--- ---
## 📝 Änderungsprotokoll ## 📝 Änderungsprotokoll
### 15.02.2026 ### 15.02.2026
- **Multi-Server Orchestration (Phase 1-8) abgeschlossen:**
- SSH-Infrastruktur: sv-payload → sv-frontend (key: frontend_deploy), Hetzner 1/2 (key: plesk_deploy)
- payload-contracts Repo: Shared types, API client, block registry (Git-Dependency)
- Work-Order-System: `create-work-order.sh` + `execute-work-order.sh` für CMS→Frontend-Koordination
- blogwoman.de: Migration auf Contracts-Client (Bridge-Pattern), live auf Hetzner 1
- porwoll.de: Direkte Contracts-Types, 9 Blocks, live auf Hetzner 2
- Plesk Production: nginx-only + Passenger 6.1.0, GitHub Webhooks (Auto-Deploy)
- CI/CD: Lint+Build CI, Staging-Deploy via SSH (UDM Pro SE Port-Forward 37.24.237.181:2204)
- Claude Code v2.1.37 auf sv-frontend mit CLAUDE.md in allen Repos
- **Monitoring & Alerting Dashboard implementiert:** - **Monitoring & Alerting Dashboard implementiert:**
- 4 neue Collections: MonitoringSnapshots, MonitoringLogs, MonitoringAlertRules, MonitoringAlertHistory - 4 neue Collections: MonitoringSnapshots, MonitoringLogs, MonitoringAlertRules, MonitoringAlertHistory
- Backend-Services: MonitoringService, PerformanceTracker, MonitoringLogger, AlertEvaluator, SnapshotCollector - Backend-Services: MonitoringService, PerformanceTracker, MonitoringLogger, AlertEvaluator, SnapshotCollector

View file

@ -2,12 +2,125 @@
> **Server:** sv-frontend (LXC 704) - 10.10.181.104 > **Server:** sv-frontend (LXC 704) - 10.10.181.104
> **Backend API:** https://cms.c2sgmbh.de/api (Production) > **Backend API:** https://cms.c2sgmbh.de/api (Production)
> **Shared Types:** `@c2s/payload-contracts` (Git-Dependency)
## Übersicht ## Übersicht
Das Frontend wird als separates Next.js-Projekt entwickelt und nutzt Payload CMS als Headless CMS über die REST-API. Jedes Frontend ist ein separates Next.js-Projekt und nutzt Payload CMS als Headless CMS über die REST-API. Alle Frontends teilen sich TypeScript-Typen und den API-Client über das `payload-contracts` Package.
**Wichtig:** Die Frontend-Entwicklung verwendet die **Produktions-API und -Datenbank**, um mit echten Inhalten zu arbeiten. SEO-Einstellungen und Cookie-Consent-Konfigurationen werden ebenfalls aus der Produktionsumgebung geladen. **Architektur:**
```
CMS (payload-cms) payload-contracts Frontends (Next.js)
━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━
Collections + Blocks → Shared Types → frontend.porwoll.de
payload-types.ts → API Client → frontend.blogwoman.de
Block Registry → (7 weitere)
```
---
## payload-contracts (Shared Package)
Alle Frontends verwenden `@c2s/payload-contracts` als Git-Dependency für TypeScript-Typen, den API-Client und die Block-Registry.
### Installation
```json
// package.json
{
"dependencies": {
"@c2s/payload-contracts": "github:complexcaresolutions/payload-contracts#main"
}
}
```
### Imports
```typescript
// Types
import type { Page, Post, Media } from '@c2s/payload-contracts/types'
import type { Block, BlockByType } from '@c2s/payload-contracts/types'
// API Client
import { createPayloadClient } from '@c2s/payload-contracts/api-client'
// Block Renderer
import { createBlockRenderer } from '@c2s/payload-contracts/blocks'
// Constants
import { TENANTS } from '@c2s/payload-contracts/constants'
```
### API Client erstellen
```typescript
// src/lib/api.ts
import { createPayloadClient } from '@c2s/payload-contracts/api-client'
export const api = createPayloadClient({
baseUrl: process.env.NEXT_PUBLIC_PAYLOAD_URL!,
tenantId: Number(process.env.NEXT_PUBLIC_TENANT_ID),
})
// Verwendung
const page = await api.pages.getBySlug('home')
const posts = await api.posts.getAll({ limit: 10 })
const nav = await api.navigation.get()
const settings = await api.settings.get()
```
### Block Renderer
```typescript
// src/components/blocks/index.tsx
import { createBlockRenderer } from '@c2s/payload-contracts/blocks'
import { HeroBlock } from './HeroBlock'
import { TextBlock } from './TextBlock'
// ... weitere Block-Imports
export const BlockRenderer = createBlockRenderer({
'hero-block': HeroBlock,
'text-block': TextBlock,
// ... nur die Blocks registrieren, die das Frontend braucht
})
```
### Block-Komponente implementieren
```typescript
// src/components/blocks/HeroBlock.tsx
import type { BlockByType } from '@c2s/payload-contracts/types'
type HeroBlockData = BlockByType<'hero-block'>
interface HeroBlockProps {
block: HeroBlockData
}
export function HeroBlock({ block }: HeroBlockProps) {
return (
<section>
<h1>{block.headline}</h1>
{block.subline && <p>{block.subline}</p>}
</section>
)
}
```
### Types aktualisieren
Wenn sich CMS-Collections oder Blocks ändern:
```bash
# Auf sv-payload:
cd ~/payload-cms && pnpm payload generate:types
cd ~/payload-contracts && pnpm extract
git add -A && git commit -m "types: update from CMS" && git push
# Auf sv-frontend (pro Projekt):
cd ~/frontend.porwoll.de
pnpm update @c2s/payload-contracts
```
--- ---
@ -29,15 +142,87 @@ NEXT_PUBLIC_TENANT_ID=4
NEXT_PUBLIC_TENANT_SLUG=c2s NEXT_PUBLIC_TENANT_SLUG=c2s
``` ```
### Tenant-IDs
| ID | Name | Slug | Domain | Status |
|----|------|------|--------|--------|
| 1 | porwoll.de | porwoll | porwoll.de | ✅ Live |
| 4 | Complex Care Solutions GmbH | c2s | complexcaresolutions.de | Geplant |
| 5 | Gunshin | gunshin | gunshin.de | Geplant |
| 9 | BlogWoman | blogwoman | blogwoman.de | ✅ Live |
### Warum Production-Daten? ### Warum Production-Daten?
| Aspekt | Grund | Die Frontend-Entwicklung verwendet die Produktions-API, um mit echten Inhalten zu arbeiten. SEO-Einstellungen und Cookie-Consent-Konfigurationen werden ebenfalls aus der Produktionsumgebung geladen.
|--------|-------|
| **Content** | Echte Inhalte für realistische Entwicklung | ---
| **SEO** | Produktions-Meta-Tags und Structured Data |
| **Cookie-Consent** | Live Cookie-Konfigurationen (DSGVO-relevant) | ## CI/CD Pipeline
| **Media** | Produktions-Bilder mit allen Größen |
| **Consistency** | Keine Sync-Probleme zwischen Dev/Prod | ### CI (Lint + Build)
Jedes Frontend hat eine GitHub Actions CI-Pipeline, die bei Push auf `develop` und `main` läuft.
```yaml
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [develop, main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with: { node-version: 22, cache: pnpm }
- run: pnpm install --frozen-lockfile
- run: pnpm lint
- run: pnpm build
```
### Staging-Deploy (sv-frontend)
Push auf `develop` → GitHub Actions → SSH via UDM Pro SE Port-Forward → Build auf sv-frontend.
```yaml
# .github/workflows/deploy-staging.yml
# SSH-Credentials als Repository-Secrets: SSH_HOST, SSH_PORT, SSH_USER, SSH_PRIVATE_KEY
```
### Production-Deploy (Plesk)
Push auf `main` → GitHub Webhook → Plesk Git Pull → `pnpm install && pnpm build` → Passenger Restart.
Production-Deployment wird NICHT über GitHub Actions gesteuert, sondern über Plesk Git-Integration mit Webhooks.
### Deployment-Flow
```
develop (sv-frontend) → CI ✅ → Staging-Test (*-dev.porwoll.tech)
main (merge) → CI ✅ → Webhook → Plesk → Production ✅
```
---
## Work-Order-System
Wenn ein neuer Block oder eine neue Collection im CMS erstellt wird, koordiniert das Work-Order-System die Frontend-Implementierung.
### Ablauf
1. **sv-payload:** CMS ändern → Types extrahieren → Work Order schreiben
2. **sv-frontend:** Work Order lesen → `pnpm update @c2s/payload-contracts` → Block implementieren
### Referenz
Vollständige Dokumentation im `payload-contracts` Repo:
- `work-orders/_template.md` — Vorlage
- `scripts/create-work-order.sh` — Work Order erstellen (auf sv-payload)
- `scripts/execute-work-order.sh` — Work Order ausführen (auf sv-frontend)
--- ---
@ -51,80 +236,31 @@ NEXT_PUBLIC_TENANT_SLUG=c2s
--- ---
## Offene Frontend-Tasks ## Frontend-Status
### Hohe Priorität ### Live
- [ ] **Block-Komponenten entwickeln** | Frontend | Production | Blocks | Contracts |
- [ ] Hero Block |----------|-----------|--------|-----------|
- [ ] Hero Slider Block | porwoll.de | ✅ Hetzner 2 | 9 implementiert | Direkte Types |
- [ ] Text Block | blogwoman.de | ✅ Hetzner 1 | Alle implementiert | Bridge-Pattern (lokale types.ts) |
- [ ] Image Text Block
- [ ] Card Grid Block
- [ ] Quote Block
- [ ] CTA Block
- [ ] Contact Form Block
- [ ] Video Block
- [ ] Divider Block
- [ ] Timeline Block
- [ ] Posts List Block
- [ ] Testimonials Block
- [ ] Newsletter Block
- [ ] Process Steps Block
- [ ] FAQ Block
- [ ] Team Block
- [ ] Services Block
- [ ] **Newsletter-Anmelde-Formular** ### Geplant
- API: `POST /api/newsletter/subscribe`
- Double Opt-In Flow bereits im Backend implementiert
- Felder: email, firstName (optional), tenantId, source
- [ ] **Cookie-Banner implementieren** | Frontend | Server | Priorität |
- Cookie Configurations aus Production-API laden |----------|--------|-----------|
- Consent-Logs an Backend senden | complexcaresolutions.de | Hetzner 1 | Hoch |
- DSGVO-konform mit Opt-In | caroline-porwoll.com | Hetzner 2 | Mittel |
| caroline-porwoll.de | Hetzner 2 | Mittel |
| gunshin.de | - | Niedrig |
| zweitmeinu.ng | Hetzner 1 | Niedrig |
### Mittlere Priorität ### Offene Tasks
- [ ] **Multi-Tenant Routing** - [ ] porwoll.de: Fehlende Blocks implementieren (~6 via Work Orders)
- Domain-basierte Tenant-Erkennung - [ ] blogwoman.de: Bridge-Pattern durch direkte Contracts-Imports ersetzen
- Locale-Routing (`/[locale]/...`) - [ ] Cookie-Banner implementieren (DSGVO)
- Unterstützte Locales: `de` (default), `en` - [ ] Newsletter-Formular-Komponente
- [ ] **SEO-Integration**
- Meta-Tags aus Pages/Posts (Production)
- Structured Data (JSON-LD)
- Sitemap: https://cms.c2sgmbh.de/sitemap.xml
- [ ] **Suche implementieren**
- API: `GET /api/search?q=...&locale=de`
- Auto-Complete: `GET /api/search/suggestions?q=...`
- Rate-Limit: 30 Requests/Minute
### Tenant-spezifische Features
#### porwoll.de
- [ ] Portfolio-Galerie (Fotografie)
- [ ] Buchungsformular
- [ ] Before/After Bildvergleich
#### complexcaresolutions.de (C2S)
- [ ] Team-Übersicht
- [ ] Leistungs-Seiten
- [ ] Zertifizierungen
- [ ] Karriere-Seite mit Stellenangeboten
#### gunshin.de (Game Development)
- [ ] Projekt-Galerie
- API: `GET /api/projects?where[tenant][equals]=5`
- [ ] Portfolio-Seiten
- [ ] Referenzen-Slider
#### zweitmein.ng
- [ ] FAQ-Sektion
- [ ] Preistabellen
- [ ] Kontaktformular
--- ---
@ -149,21 +285,7 @@ NEXT_PUBLIC_TENANT_SLUG=c2s
| Favorites | `GET /api/favorites` | Affiliate-Produkte (BlogWoman) | | Favorites | `GET /api/favorites` | Affiliate-Produkte (BlogWoman) |
| Series | `GET /api/series` | YouTube-Serien (BlogWoman) | | Series | `GET /api/series` | YouTube-Serien (BlogWoman) |
### Community Management (YouTube/Meta) ### Site Settings & Navigation (Tenant-isoliert)
| Collection | Endpoint | Beschreibung |
|------------|----------|--------------|
| YouTube Channels | `GET /api/youtube-channels` | Multi-Kanal-Verwaltung |
| YouTube Content | `GET /api/youtube-content` | Videos + Shorts mit Kommentaren |
| YT Series | `GET /api/yt-series` | Serien mit Branding (Logo, Farben) |
| YT Notifications | `GET /api/yt-notifications` | Handlungsbedarf-System |
| Social Platforms | `GET /api/social-platforms` | Plattform-Konfiguration |
| Social Accounts | `GET /api/social-accounts` | OAuth-Verbindungen |
| Community Interactions | `GET /api/community-interactions` | Kommentare/Nachrichten |
### Site Settings & Navigation (Tenant-isolierte Collections)
> **Hinweis:** SiteSettings und Navigations wurden zu tenant-spezifischen Collections umgewandelt.
| Collection | Endpoint | Beschreibung | | Collection | Endpoint | Beschreibung |
|------------|----------|--------------| |------------|----------|--------------|
@ -171,12 +293,6 @@ NEXT_PUBLIC_TENANT_SLUG=c2s
| Navigation | `GET /api/navigations?where[tenant][equals]=4` | Menü-Struktur | | Navigation | `GET /api/navigations?where[tenant][equals]=4` | Menü-Struktur |
| Privacy Policy | `GET /api/privacy-policy-settings?where[tenant][equals]=4` | Datenschutz | | Privacy Policy | `GET /api/privacy-policy-settings?where[tenant][equals]=4` | Datenschutz |
### Globals (Systemweit)
| Global | Endpoint | Beschreibung |
|--------|----------|--------------|
| SEO Settings | `GET /api/globals/seo-settings` | Default SEO (Production) |
### Spezielle Endpoints ### Spezielle Endpoints
| Endpoint | Methode | Beschreibung | | Endpoint | Methode | Beschreibung |
@ -184,8 +300,6 @@ NEXT_PUBLIC_TENANT_SLUG=c2s
| `/api/search` | GET | Volltextsuche | | `/api/search` | GET | Volltextsuche |
| `/api/search/suggestions` | GET | Auto-Complete | | `/api/search/suggestions` | GET | Auto-Complete |
| `/api/newsletter/subscribe` | POST | Newsletter-Anmeldung | | `/api/newsletter/subscribe` | POST | Newsletter-Anmeldung |
| `/api/timelines` | GET | Timeline-Daten |
| `/api/workflows` | GET | Workflow-Daten |
--- ---
@ -194,24 +308,14 @@ NEXT_PUBLIC_TENANT_SLUG=c2s
Alle Collection-Anfragen sollten nach Tenant gefiltert werden: Alle Collection-Anfragen sollten nach Tenant gefiltert werden:
```typescript ```typescript
// Beispiel: Posts für Tenant "c2s" (ID: 4) // Mit payload-contracts API Client (empfohlen):
const posts = await api.posts.getAll({ limit: 10 })
// → Tenant-Filter wird automatisch angewendet
// Manuell:
fetch('https://cms.c2sgmbh.de/api/posts?where[tenant][equals]=4&locale=de') fetch('https://cms.c2sgmbh.de/api/posts?where[tenant][equals]=4&locale=de')
// Beispiel: Pages für Tenant "gunshin" (ID: 5)
fetch('https://cms.c2sgmbh.de/api/pages?where[tenant][equals]=5&locale=de')
// Beispiel: SEO-Settings (Global, kein Tenant-Filter)
fetch('https://cms.c2sgmbh.de/api/globals/seo-settings')
``` ```
### Tenant-IDs
| ID | Name | Slug | Domain |
|----|------|------|--------|
| 1 | porwoll.de | porwoll | porwoll.de |
| 4 | Complex Care Solutions GmbH | c2s | complexcaresolutions.de |
| 5 | Gunshin | gunshin | gunshin.de |
--- ---
## Bild-Optimierung ## Bild-Optimierung
@ -259,8 +363,6 @@ fetch('https://cms.c2sgmbh.de/api/posts?locale=en')
## Newsletter-Integration ## Newsletter-Integration
### Anmeldung
```typescript ```typescript
const response = await fetch('https://cms.c2sgmbh.de/api/newsletter/subscribe', { const response = await fetch('https://cms.c2sgmbh.de/api/newsletter/subscribe', {
method: 'POST', method: 'POST',
@ -272,148 +374,13 @@ const response = await fetch('https://cms.c2sgmbh.de/api/newsletter/subscribe',
source: 'footer' // optional: Herkunft source: 'footer' // optional: Herkunft
}) })
}) })
// Response: { success: true, message: '...' }
``` ```
### Flow **Flow:** Subscribe → Double Opt-In E-Mail → Bestätigung → Willkommens-E-Mail
1. User gibt E-Mail ein → `POST /api/newsletter/subscribe`
2. Backend sendet Double Opt-In E-Mail
3. User klickt Bestätigungs-Link
4. Backend sendet Willkommens-E-Mail
5. User kann sich über Link in E-Mails abmelden
--- ---
## Cookie-Consent (Production-Daten) ## Rate-Limits
### Konfiguration laden
```typescript
// Cookie-Konfiguration aus Production laden
const config = await fetch('https://cms.c2sgmbh.de/api/cookie-configurations?where[tenant][equals]=4')
.then(r => r.json())
// config.docs enthält:
// - Kategorien (necessary, analytics, marketing, etc.)
// - Cookie-Details pro Kategorie
// - Texte für Banner (lokalisiert)
```
### Consent loggen
```typescript
await fetch('https://cms.c2sgmbh.de/api/consent-logs', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
tenant: 4,
consentGiven: true,
categories: ['necessary', 'analytics'],
ipAddress: '...', // Optional, für DSGVO
userAgent: navigator.userAgent
})
})
```
---
## SEO-Integration (Production-Daten)
### Global SEO-Settings
```typescript
// SEO-Defaults aus Production laden
const seoSettings = await fetch('https://cms.c2sgmbh.de/api/globals/seo-settings')
.then(r => r.json())
// Enthält:
// - defaultTitle, titleTemplate
// - defaultDescription
// - defaultImage (OG-Image)
// - robotsDefault
```
### Page-spezifische SEO
```typescript
// SEO-Daten aus Page laden
const page = await fetch('https://cms.c2sgmbh.de/api/pages?where[slug][equals]=about&where[tenant][equals]=4')
.then(r => r.json())
// page.docs[0].meta enthält:
// - title, description
// - image (OG-Image Override)
// - noIndex, noFollow
```
### Sitemap
Die Sitemap wird automatisch von Payload generiert:
- **URL:** https://cms.c2sgmbh.de/sitemap.xml
- Enthält alle publizierten Pages und Posts
---
## Kontaktformular
Formular-Submissions werden über die Forms-Collection verarbeitet:
```typescript
await fetch('https://cms.c2sgmbh.de/api/form-submissions', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
form: 1, // Form-ID
submissionData: [
{ field: 'name', value: 'Max Mustermann' },
{ field: 'email', value: 'max@example.com' },
{ field: 'message', value: 'Ihre Nachricht...' }
]
})
})
```
---
## Authentifizierung (optional)
Falls User-Authentifizierung benötigt wird:
```typescript
// Login
const { token, user } = await fetch('https://cms.c2sgmbh.de/api/users/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password })
}).then(r => r.json())
// Authentifizierte Requests
fetch('https://cms.c2sgmbh.de/api/...', {
headers: { 'Authorization': `JWT ${token}` }
})
```
---
## Entwicklungshinweise
### TypeScript-Typen
Die Payload-Typen können aus dem Backend exportiert werden:
```bash
# Auf dem Payload-Server (Production)
ssh payload@162.55.85.18
cd ~/payload-cms
pnpm payload generate:types
# Datei: src/payload-types.ts
```
Diese Datei kann ins Frontend-Projekt kopiert werden für typsichere API-Calls.
### Rate-Limits
| Endpoint | Limit | | Endpoint | Limit |
|----------|-------| |----------|-------|
@ -422,18 +389,6 @@ Diese Datei kann ins Frontend-Projekt kopiert werden für typsichere API-Calls.
| Newsletter | 5/10min | | Newsletter | 5/10min |
| Formulare | 5/10min | | Formulare | 5/10min |
### Caching
- API-Responses werden serverseitig gecacht (Redis)
- TTL: 60 Sekunden für Suche
- Cache wird bei Content-Änderungen invalidiert
### CORS
Die Production-API erlaubt Requests von:
- `*.porwoll.tech` (Development)
- `porwoll.de`, `complexcaresolutions.de`, `gunshin.de` (Production)
--- ---
## Development Server (sv-frontend) ## Development Server (sv-frontend)
@ -455,72 +410,55 @@ pnpm dev
### AI-Tools ### AI-Tools
```bash ```bash
claude # Claude Code CLI claude # Claude Code CLI (v2.1.37)
codex # Codex CLI codex # Codex CLI
gemini # Gemini CLI gemini # Gemini CLI
``` ```
### Service-Management
```bash
# Systemd Service starten
systemctl start frontend-porwoll
# Service stoppen
systemctl stop frontend-porwoll
# Logs anzeigen
journalctl -u frontend-porwoll -f
```
--- ---
## Community Management Integration ## ESLint-Konfiguration
### YouTube-Inhalte abrufen Alle Frontends verwenden die gleiche ESLint-Konfiguration:
```typescript ```javascript
// Alle Videos eines Kanals // eslint.config.mjs
const videos = await fetch( import { defineConfig, globalIgnores } from "eslint/config";
'https://cms.c2sgmbh.de/api/youtube-content?where[channel][equals]=1&where[contentType][equals]=video' import nextVitals from "eslint-config-next/core-web-vitals";
).then(r => r.json()) import nextTs from "eslint-config-next/typescript";
// Serien eines Kanals const eslintConfig = defineConfig([
const series = await fetch( ...nextVitals,
'https://cms.c2sgmbh.de/api/yt-series?where[channel][equals]=1&where[isActive][equals]=true' ...nextTs,
).then(r => r.json()) {
rules: {
"@typescript-eslint/no-unused-vars": ["warn", {
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
destructuredArrayIgnorePattern: "^_",
}],
},
},
globalIgnores([".next/**", "out/**", "build/**", "next-env.d.ts", "server.js"]),
]);
// Videos einer Serie export default eslintConfig;
const seriesVideos = await fetch(
'https://cms.c2sgmbh.de/api/youtube-content?where[series][equals]=1'
).then(r => r.json())
``` ```
### Kommentare/Interaktionen (Auth erforderlich) `server.js` wird ignoriert, da es CJS für Phusion Passenger verwendet.
```typescript
// Kommentare eines Videos
const comments = await fetch(
'https://cms.c2sgmbh.de/api/community-interactions?where[contentId][equals]=VIDEO_ID',
{ headers: { 'Authorization': `JWT ${token}` } }
).then(r => r.json())
// Ungelesene Benachrichtigungen
const notifications = await fetch(
'https://cms.c2sgmbh.de/api/yt-notifications?where[status][equals]=unread',
{ headers: { 'Authorization': `JWT ${token}` } }
).then(r => r.json())
```
--- ---
## Ressourcen ## Ressourcen
- **Payload CMS Docs:** https://payloadcms.com/docs | Ressource | URL/Pfad |
- **API-Dokumentation:** https://cms.c2sgmbh.de/api/docs |-----------|----------|
- **Backend-Repository:** https://github.com/complexcaresolutions/cms.c2sgmbh.git | Payload CMS Docs | https://payloadcms.com/docs |
- **Analytics:** https://analytics.c2sgmbh.de | API-Dokumentation | https://cms.c2sgmbh.de/api/docs |
| payload-contracts | https://github.com/complexcaresolutions/payload-contracts |
| Infrastruktur-Docs | `docs/INFRASTRUCTURE.md` |
| Analytics | https://analytics.c2sgmbh.de |
--- ---
*Letzte Aktualisierung: 17.01.2026* *Letzte Aktualisierung: 15.02.2026*