# 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*
