cms.c2sgmbh/CLAUDE.md
Martin Porwoll 966af755b4 docs: update CLAUDE.md and TODO.md with recent features
- Add E-Mail system documentation (tenant-specific SMTP, API endpoint)
- Add Redis caching section
- Add complete Collections and Globals overview
- Update project structure with new directories
- Mark Portfolio collections and Email system as completed
- Update environment variables documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-07 20:22:05 +00:00

273 lines
7.8 KiB
Markdown

# Payload CMS Multi-Tenant Project
## Projektübersicht
Multi-Tenant CMS für 4 Websites unter einer Payload CMS 3.x Instanz:
- porwoll.de
- complexcaresolutions.de
- gunshin.de
- zweitmein.ng
## Tech Stack
- **CMS:** Payload CMS 3.x
- **Framework:** Next.js 15.4.7
- **Sprache:** TypeScript
- **Datenbank:** PostgreSQL 17 (separater Server)
- **Reverse Proxy:** Caddy 2.10.2 mit Let's Encrypt
- **Process Manager:** PM2
- **Package Manager:** pnpm
## Architektur
```
Internet → 37.24.237.181 → Caddy (443) → Payload (3000)
PostgreSQL (10.10.181.101:5432)
```
| Server | IP | Funktion |
| --------------------- | ------------- | ---------- |
| sv-payload (LXC 700) | 10.10.181.100 | App Server |
| sv-postgres (LXC 701) | 10.10.181.101 | Datenbank |
## Wichtige Pfade
```
/home/payload/payload-cms/ # Projektroot
├── src/
│ ├── payload.config.ts # Haupt-Konfiguration
│ ├── collections/ # Alle Collections
│ │ ├── Users.ts
│ │ ├── Media.ts
│ │ ├── Tenants.ts
│ │ ├── Posts.ts
│ │ ├── Categories.ts
│ │ ├── Portfolios.ts
│ │ ├── PortfolioCategories.ts
│ │ ├── EmailLogs.ts
│ │ └── ...
│ ├── lib/
│ │ ├── email/ # E-Mail-System
│ │ │ ├── tenant-email-service.ts
│ │ │ └── payload-email-adapter.ts
│ │ ├── search.ts # Volltextsuche
│ │ └── redis.ts # Redis Cache Client
│ └── hooks/ # Collection Hooks
│ ├── sendFormNotification.ts
│ └── invalidateEmailCache.ts
├── .env # Umgebungsvariablen
├── ecosystem.config.cjs # PM2 Config
└── .next/ # Build Output
```
## Umgebungsvariablen (.env)
```env
DATABASE_URI=postgresql://payload:Finden55@10.10.181.101:5432/payload_db
PAYLOAD_SECRET=a53b254070d3fffd2b5cfcc3
PAYLOAD_PUBLIC_SERVER_URL=https://pl.c2sgmbh.de
NEXT_PUBLIC_SERVER_URL=https://pl.c2sgmbh.de
NODE_ENV=production
PORT=3000
# E-Mail (Global Fallback)
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=user@example.com
SMTP_PASS=secret
SMTP_FROM_ADDRESS=noreply@c2sgmbh.de
SMTP_FROM_NAME=Payload CMS
# Redis Cache
REDIS_URL=redis://localhost:6379
```
## Multi-Tenant Plugin
Verwendet `@payloadcms/plugin-multi-tenant` für Mandantenfähigkeit.
**Aktuelle Tenants:**
| ID | Name | Slug |
|----|------|------|
| 1 | porwoll.de | porwoll |
| 4 | Complex Care Solutions GmbH | c2s |
| 5 | Gunshin | gunshin |
**User-Tenant-Zuweisung:** Tabelle `users_tenants`
## Wichtige Befehle
```bash
# Entwicklung
pnpm dev
# Production Build
pnpm build
# Migrationen
pnpm payload migrate:create
pnpm payload migrate
# ImportMap nach Plugin-Änderungen
pnpm payload generate:importmap
# PM2
pm2 status
pm2 logs payload
pm2 restart payload
# Datenbank prüfen
PGPASSWORD=Finden55 psql -h 10.10.181.101 -U payload -d payload_db
```
## Workflow nach Code-Änderungen
1. Code ändern
2. `pnpm build`
3. `pm2 restart payload`
4. Testen unter https://pl.c2sgmbh.de/admin
## Bekannte Besonderheiten
- **ES Modules:** package.json hat `"type": "module"`, daher PM2 Config als `.cjs`
- **Plugin ImportMap:** Nach Plugin-Änderungen `pnpm payload generate:importmap` ausführen
- **User-Tenant-Zuweisung:** Neue User müssen manuell Tenants zugewiesen bekommen
## Build-Konfiguration
Der Build ist für speichereffizientes Kompilieren optimiert:
- `package.json`: `--max-old-space-size=2048` (2GB Heap-Limit)
- `next.config.mjs`: `experimental.cpus: 1`, `workerThreads: false`
**WICHTIG:** Der Server hat nur 4GB RAM ohne Swap. Bei laufendem VS Code Server muss der Build mit reduziertem Memory ausgeführt werden:
```bash
pm2 stop payload # Speicher freigeben
NODE_OPTIONS="--no-deprecation --max-old-space-size=1024" ./node_modules/.bin/next build
pm2 start payload
```
Ohne PM2-Stop und mit VS Code wird der Build vom OOM Killer beendet (Exit code 137).
## Mehrsprachigkeit (i18n)
Das System unterstützt Deutsch (default) und Englisch:
- **Admin UI:** `@payloadcms/translations` für DE/EN
- **Content:** Localization mit Fallback auf Deutsch
- **Datenbank:** 36 `_locales` Tabellen für lokalisierte Felder
- **API:** `?locale=de` oder `?locale=en` Parameter
- **Frontend:** Routing über `/[locale]/...`
```bash
# Locales in der Datenbank prüfen
PGPASSWORD=Finden55 psql -h 10.10.181.101 -U payload -d payload_db -c "\dt *_locales"
```
## URLs
- **Admin Panel:** https://pl.c2sgmbh.de/admin
- **API:** https://pl.c2sgmbh.de/api
- **E-Mail API:** https://pl.c2sgmbh.de/api/send-email (POST, Auth erforderlich)
## E-Mail-System
Multi-Tenant E-Mail-System mit tenant-spezifischer SMTP-Konfiguration:
**Architektur:**
- Globaler SMTP als Fallback (via .env)
- Tenant-spezifische SMTP in Tenants Collection
- Transporter-Caching mit automatischer Invalidierung
- EmailLogs Collection für Audit-Trail
**Tenant E-Mail-Konfiguration:**
```
Tenants → email → fromAddress, fromName, replyTo
→ email → useCustomSmtp (Checkbox)
→ email → smtp → host, port, secure, user, pass
```
**API-Endpoint `/api/send-email`:**
```bash
curl -X POST https://pl.c2sgmbh.de/api/send-email \
-H "Content-Type: application/json" \
-H "Cookie: payload-token=..." \
-d '{
"to": "empfaenger@example.com",
"subject": "Betreff",
"html": "<p>Inhalt</p>",
"tenantId": 1
}'
```
**Sicherheit:**
- Authentifizierung erforderlich
- Tenant-Zugriffskontrolle (User muss Tenant-Mitglied sein)
- Rate-Limiting: 10 E-Mails/Minute pro User
- SMTP-Passwort nie in API-Responses
## Redis Caching
Redis wird für API-Response-Caching und E-Mail-Transporter-Caching verwendet:
```typescript
import { redis } from '@/lib/redis'
// Cache setzen (TTL in Sekunden)
await redis.set('key', JSON.stringify(data), 'EX', 60)
// Cache lesen
const cached = await redis.get('key')
// Pattern-basierte Invalidierung
await redis.keys('posts:*').then(keys => keys.length && redis.del(...keys))
```
## Datenbank-Direktzugriff
```bash
PGPASSWORD=Finden55 psql -h 10.10.181.101 -U payload -d payload_db
# Nützliche Queries
SELECT * FROM tenants;
SELECT * FROM users_tenants;
SELECT * FROM email_logs ORDER BY created_at DESC LIMIT 10;
\dt -- Alle Tabellen
```
## Collections Übersicht
| Collection | Slug | Beschreibung |
|------------|------|--------------|
| Users | users | Benutzer mit isSuperAdmin Flag |
| Tenants | tenants | Mandanten mit E-Mail-Konfiguration |
| Media | media | Medien mit 11 responsive Image Sizes |
| Pages | pages | Seiten mit Blocks |
| Posts | posts | Blog/News/Presse mit Kategorien |
| Categories | categories | Kategorien für Posts |
| Portfolios | portfolios | Portfolio-Galerien (Fotografie) |
| PortfolioCategories | portfolio-categories | Kategorien für Portfolios |
| Testimonials | testimonials | Kundenbewertungen |
| NewsletterSubscribers | newsletter-subscribers | Newsletter mit Double Opt-In |
| SocialLinks | social-links | Social Media Links |
| Forms | forms | Formular-Builder |
| FormSubmissions | form-submissions | Formular-Einsendungen |
| EmailLogs | email-logs | E-Mail-Protokollierung |
| CookieConfigurations | cookie-configurations | Cookie-Banner Konfiguration |
| CookieInventory | cookie-inventory | Cookie-Inventar |
| ConsentLogs | consent-logs | Consent-Protokollierung |
## Globals
| Global | Slug | Beschreibung |
|--------|------|--------------|
| SiteSettings | site-settings | Allgemeine Website-Einstellungen |
| Navigation | navigation | Navigationsmenü |
| SEOSettings | seo-settings | SEO-Einstellungen |
| PrivacyPolicySettings | privacy-policy-settings | Datenschutz-Einstellungen |
*Letzte Aktualisierung: 07.12.2025*