- Add API documentation (API_ANLEITUNG.md) - Add architecture docs (UNIVERSAL_FEATURES.md, Analytics.md) - Add guides (FRONTEND.md, SEO_ERWEITERUNG.md, styleguide.md) - Add Planungs-KI prompt template (ANLEITUNG-PLANUNGS-KI-FRONTEND.md) - Add BlogWoman frontend development prompt with: - Tenant-ID 9 configuration - Design system based on styleguide - BlogWoman-specific blocks (Favorites, Series, VideoEmbed) - API patterns with tenant isolation - SEO and Analytics integration Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
13 KiB
Frontend-Entwicklung - Payload CMS Multi-Tenant
Server: sv-frontend (LXC 704) - 10.10.181.104 Backend API: https://cms.c2sgmbh.de/api (Production)
Übersicht
Das Frontend wird als separates Next.js-Projekt entwickelt und nutzt Payload CMS als Headless CMS über die REST-API.
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.
Umgebungskonfiguration
Environment Variables (.env.local)
# API-Endpunkte (PRODUKTION)
NEXT_PUBLIC_PAYLOAD_URL=https://cms.c2sgmbh.de
NEXT_PUBLIC_API_URL=https://cms.c2sgmbh.de/api
# Analytics (optional)
NEXT_PUBLIC_UMAMI_HOST=https://analytics.c2sgmbh.de
NEXT_PUBLIC_UMAMI_WEBSITE_ID=<website-id>
# Tenant-Konfiguration (je nach Projekt)
NEXT_PUBLIC_TENANT_ID=4
NEXT_PUBLIC_TENANT_SLUG=c2s
Warum Production-Daten?
| Aspekt | Grund |
|---|---|
| Content | Echte Inhalte für realistische Entwicklung |
| SEO | Produktions-Meta-Tags und Structured Data |
| Cookie-Consent | Live Cookie-Konfigurationen (DSGVO-relevant) |
| Media | Produktions-Bilder mit allen Größen |
| Consistency | Keine Sync-Probleme zwischen Dev/Prod |
API-Dokumentation
| Ressource | URL |
|---|---|
| Swagger UI | https://cms.c2sgmbh.de/api/docs |
| OpenAPI JSON | https://cms.c2sgmbh.de/api/openapi.json |
| REST API Base | https://cms.c2sgmbh.de/api |
Offene Frontend-Tasks
Hohe Priorität
-
Block-Komponenten entwickeln
- Hero Block
- Hero Slider Block
- Text Block
- 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
- API:
POST /api/newsletter/subscribe - Double Opt-In Flow bereits im Backend implementiert
- Felder: email, firstName (optional), tenantId, source
- API:
-
Cookie-Banner implementieren
- Cookie Configurations aus Production-API laden
- Consent-Logs an Backend senden
- DSGVO-konform mit Opt-In
Mittlere Priorität
-
Multi-Tenant Routing
- Domain-basierte Tenant-Erkennung
- Locale-Routing (
/[locale]/...) - Unterstützte Locales:
de(default),en
-
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
- API:
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
- API:
- Portfolio-Seiten
- Referenzen-Slider
zweitmein.ng
- FAQ-Sektion
- Preistabellen
- Kontaktformular
API-Endpoints
Collections
| Collection | Endpoint | Beschreibung |
|---|---|---|
| Pages | GET /api/pages |
Seiten mit Blocks |
| Posts | GET /api/posts |
Blog, News, Presse |
| Categories | GET /api/categories |
Post-Kategorien |
| Testimonials | GET /api/testimonials |
Kundenbewertungen |
| Team | GET /api/team |
Team-Mitglieder |
| Services | GET /api/services |
Leistungen |
| FAQs | GET /api/faqs |
FAQ-Einträge |
| Portfolios | GET /api/portfolios |
Portfolio-Projekte |
| Media | GET /api/media |
Medien/Bilder |
| Videos | GET /api/videos |
Video-Bibliothek |
| Timelines | GET /api/timelines |
Chronologische Events |
| Workflows | GET /api/workflows |
Prozess-Darstellungen |
| Favorites | GET /api/favorites |
Affiliate-Produkte (BlogWoman) |
| Series | GET /api/series |
YouTube-Serien (BlogWoman) |
Community Management (YouTube/Meta)
| 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 |
|---|---|---|
| Site Settings | GET /api/site-settings?where[tenant][equals]=4 |
Logo, Name, Kontakt, Adresse |
| Navigation | GET /api/navigations?where[tenant][equals]=4 |
Menü-Struktur |
| 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
| Endpoint | Methode | Beschreibung |
|---|---|---|
/api/search |
GET | Volltextsuche |
/api/search/suggestions |
GET | Auto-Complete |
/api/newsletter/subscribe |
POST | Newsletter-Anmeldung |
/api/timelines |
GET | Timeline-Daten |
/api/workflows |
GET | Workflow-Daten |
Tenant-Filterung
Alle Collection-Anfragen sollten nach Tenant gefiltert werden:
// Beispiel: Posts für Tenant "c2s" (ID: 4)
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
Media-Objekte enthalten mehrere Größen:
interface Media {
url: string // Original
sizes: {
thumbnail: { url, width, height } // 150x150
small: { url, width, height } // 300x300
medium: { url, width, height } // 600x600
large: { url, width, height } // 1200x1200
xlarge: { url, width, height } // 1920x1920
'2k': { url, width, height } // 2560x2560
og: { url, width, height } // 1200x630 (Social)
// + AVIF-Varianten
thumbnail_avif: { url, width, height }
small_avif: { url, width, height }
// ...
}
focalX?: number // Fokuspunkt X (0-100)
focalY?: number // Fokuspunkt Y (0-100)
}
Lokalisierung
Unterstützte Locales: de (default), en
// Deutsch (default)
fetch('https://cms.c2sgmbh.de/api/posts?locale=de')
// Englisch
fetch('https://cms.c2sgmbh.de/api/posts?locale=en')
// Fallback: Wenn EN nicht vorhanden, wird DE zurückgegeben
Newsletter-Integration
Anmeldung
const response = await fetch('https://cms.c2sgmbh.de/api/newsletter/subscribe', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: 'user@example.com',
firstName: 'Max', // optional
tenantId: 4, // Pflicht
source: 'footer' // optional: Herkunft
})
})
// Response: { success: true, message: '...' }
Flow
- User gibt E-Mail ein →
POST /api/newsletter/subscribe - Backend sendet Double Opt-In E-Mail
- User klickt Bestätigungs-Link
- Backend sendet Willkommens-E-Mail
- User kann sich über Link in E-Mails abmelden
Cookie-Consent (Production-Daten)
Konfiguration laden
// 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
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
// 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
// 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:
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:
// 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:
# 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 |
|---|---|
| Öffentliche API | 60/min |
| Suche | 30/min |
| Newsletter | 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)
SSH-Zugang
ssh frontend@10.10.181.104
Projekt starten
cd ~/frontend.porwoll.de
pnpm dev
# Läuft auf Port 3000 → https://porwoll-dev.porwoll.tech
AI-Tools
claude # Claude Code CLI
codex # Codex CLI
gemini # Gemini CLI
Service-Management
# Systemd Service starten
systemctl start frontend-porwoll
# Service stoppen
systemctl stop frontend-porwoll
# Logs anzeigen
journalctl -u frontend-porwoll -f
Community Management Integration
YouTube-Inhalte abrufen
// Alle Videos eines Kanals
const videos = await fetch(
'https://cms.c2sgmbh.de/api/youtube-content?where[channel][equals]=1&where[contentType][equals]=video'
).then(r => r.json())
// Serien eines Kanals
const series = await fetch(
'https://cms.c2sgmbh.de/api/yt-series?where[channel][equals]=1&where[isActive][equals]=true'
).then(r => r.json())
// Videos einer Serie
const seriesVideos = await fetch(
'https://cms.c2sgmbh.de/api/youtube-content?where[series][equals]=1'
).then(r => r.json())
Kommentare/Interaktionen (Auth erforderlich)
// 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
- Payload CMS Docs: https://payloadcms.com/docs
- API-Dokumentation: https://cms.c2sgmbh.de/api/docs
- Backend-Repository: https://github.com/complexcaresolutions/cms.c2sgmbh.git
- Analytics: https://analytics.c2sgmbh.de
Letzte Aktualisierung: 17.01.2026