mirror of
https://github.com/complexcaresolutions/frontend.blogwoman.de.git
synced 2026-03-17 16:14:00 +00:00
- 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>
526 lines
13 KiB
Markdown
526 lines
13 KiB
Markdown
# 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)
|
|
|
|
```env
|
|
# 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
|
|
|
|
- [ ] **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
|
|
|
|
### 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
|
|
|
|
---
|
|
|
|
## 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:
|
|
|
|
```typescript
|
|
// 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:
|
|
|
|
```typescript
|
|
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`
|
|
|
|
```typescript
|
|
// 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
|
|
|
|
```typescript
|
|
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
|
|
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)
|
|
|
|
### 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 |
|
|
|----------|-------|
|
|
| Ö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
|
|
|
|
```bash
|
|
ssh frontend@10.10.181.104
|
|
```
|
|
|
|
### Projekt starten
|
|
|
|
```bash
|
|
cd ~/frontend.porwoll.de
|
|
pnpm dev
|
|
# Läuft auf Port 3000 → https://porwoll-dev.porwoll.tech
|
|
```
|
|
|
|
### AI-Tools
|
|
|
|
```bash
|
|
claude # Claude Code CLI
|
|
codex # Codex 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
|
|
|
|
### YouTube-Inhalte abrufen
|
|
|
|
```typescript
|
|
// 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)
|
|
|
|
```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
|
|
|
|
- **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*
|