
Warum wir Payload CMS für unser eigenes CRM gewählt haben — und was wir dabei über TypeScript-native Headless CMS, AWS-Hosting und Next.js-Integration gelernt haben.
Einleitung
Die meisten CMS-Vergleiche bleiben theoretisch. Feature-Tabellen, Preisvergleiche, Architekturdiagramme — aber selten zeigt jemand, wie ein Headless CMS in einem echten Projekt funktioniert, wenn es über Blog-Posts und Landingpages hinausgeht.
Wir bei codehero GmbH haben genau das getan: Wir haben unser eigenes internes CRM-System mit Payload CMS gebaut. Kunden, Kontakte, Projekte, Angebote, Rechnungen mit ZUGFeRD-Standard, Zeiterfassung, Sales-Pipeline — alles in einer Next.js-App mit Payload als Daten-Backend.
In diesem Artikel teilen wir unsere Erfahrungen: Was hat funktioniert, wo mussten wir improvisieren, und warum wir Payload CMS jetzt auch unseren Kunden empfehlen.
Warum ein eigenes CRM?
Klar, es gibt Hunderte CRM-Systeme. HubSpot, Salesforce, Pipedrive — alle ausgereift, alle funktional. Aber für eine kleine Agentur mit sehr spezifischen Anforderungen bringen sie alle dasselbe Problem mit: Sie lösen 80% der Use Cases, aber die restlichen 20% kosten 80% der Zeit.
Unsere Anforderungen waren speziell:
- ZUGFeRD-Rechnungen im PDF/A-3-Format mit eingebettetem EN16931-XML — Pflicht für B2B in Deutschland
- Angebots-PDFs im eigenen CI mit automatischem Anschreiben via Claude API
- Event-Driven Architecture — das CRM soll über AWS EventBridge mit unserer SEO-Pipeline kommunizieren
- Deutsche Buchhaltungslogik — Nummernkreise (ANG-2026-0001), MwSt.-Berechnung, Zahlungsziele, Fälligkeitsdaten
Kein SaaS-CRM bietet das out of the box. Also haben wir es selbst gebaut — und Payload CMS war die perfekte Grundlage dafür.
Warum Payload CMS und nicht Strapi oder Sanity?
Die kurze Antwort: Payload lebt in unserer Next.js-App, nicht daneben.
Wir haben in den letzten Jahren mit Sanity und Strapi (für Kundenprojekte) und headless CMS gearbeitet. Jedes System hat seine Stärken. Aber für ein internes Tool, das wir selbst warten und erweitern, war Payload die logische Wahl:
TypeScript-native Konfiguration — Kein JSON-Schema, kein YAML, kein GUI-Builder. Collections werden als TypeScript-Objekte definiert. Der Compiler fängt Fehler ab, bevor sie in die Datenbank gelangen.
Payload 3.x lebt in Next.js — Kein separater Backend-Server. Das Admin Panel ist eine Route in unserer Next.js-App. Die Payload Local API greift direkt auf die Datenbank zu — ohne HTTP-Overhead, ohne CORS, ohne API-Keys.
Hooks für alles — Before-Change-Hooks berechnen unsere Netto/Brutto-Beträge automatisch. After-Change-Hooks triggern Lambda-Funktionen für PDF-Generierung. Alles deklarativ, alles typsicher.
PostgreSQL — Für ein CRM mit Beziehungen zwischen Kunden, Kontakten, Projekten, Angeboten und Rechnungen ist eine relationale Datenbank die richtige Wahl. Payload unterstützt PostgreSQL nativ über den offiziellen Adapter.
Unsere CRM-Architektur im Detail
Das System besteht aus 11 Collections und 1 Global:
Kern-Collections:
- Kunden — Firma, Branche, Adresse, Status (Lead → Aktiv → Ehemalig)
- Kontakte — Verknüpft mit Kunden, inklusive Position und LinkedIn-Profil
- Projekte — Budget, Zeitraum, Typ (Website, WebApp, API, Beratung, SEO)
Finanzen:
- Angebote — Positionen-Array mit Einheiten (Stunden, Tage, Pauschal), automatische Betragsberechnung, PDF-Generierung via Lambda
- Rechnungen — ZUGFeRD PDF/A-3 mit EN16931-XML, automatische Fälligkeitsberechnung
- Zeiterfassung — Pro Projekt, abrechenbar/nicht abrechenbar
Sales:
- Pipeline — Kanban-ähnliche Phasen (Lead → Erstgespräch → Angebot → Verhandlung → Gewonnen/Verloren)
- Aktivitäten — Anrufe, Emails, Meetings als Activity Log
Infrastruktur:
- Users — Payload-eigene Auth mit Rollen (Admin, Mitarbeiter)
- Media — S3-Storage für Uploads
- EmailTemplates — Vorlagen mit Variablen für Outbound
Global: Firmeneinstellungen — Firmendaten, Bankverbindung, Nummernkreise, MwSt.-Satz — wird von allen Hooks referenziert.
Hooks: Das Killer-Feature von Payload
Das Feature, das Payload von anderen Headless CMS unterscheidet, sind die Lifecycle Hooks. Für unser CRM waren sie entscheidend:
Automatische Nummernvergabe:
Jedes Angebot bekommt automatisch eine fortlaufende Nummer (ANG-2026-0001). Der Hook liest den aktuellen Zähler aus den Firmeneinstellungen, vergibt die Nummer und inkrementiert den Zähler — atomar, ohne Race Conditions.
```typescript
export const generateNummer = (type: 'angebot' | 'rechnung') =>
async ({ data, operation, req }) => {
if (operation !== 'create' || data?.nummer) return data
const settings = await req.payload.findGlobal({ slug: 'firmeneinstellungen' })
const prefix = type === 'angebot' ? 'ANG' : 'RE'
const counter = settings.nummernkreise[naechste${type}Nr] || 1
data.nummer = ${prefix}-${new Date().getFullYear()}-${String(counter).padStart(4, '0')}
// Counter inkrementieren...
return data
}
```
Automatische Betragsberechnung:
Ein Before-Change-Hook iteriert über alle Positionen, berechnet Netto, wendet Rabatt an, berechnet MwSt. und Brutto — bei jeder Änderung automatisch.
Fälligkeitsdatum:
Bei Rechnungen wird das Fälligkeitsdatum automatisch aus Rechnungsdatum + Zahlungsziel berechnet. Simple Logik, aber ein Hook spart manuelle Fehler.
PDF-Generierung:
Wenn ein Angebot auf "Gesendet" gesetzt wird, triggert ein After-Change-Hook eine Lambda-Funktion. Die Lambda nutzt die Claude API, um ein professionelles Anschreiben zu generieren, rendert alles als HTML im codehero-CI und konvertiert es mit Puppeteer zu einem A4-PDF.
ZUGFeRD: Deutsche Rechnungsstandards mit Payload
Ein besonderer Aspekt unseres CRM: ZUGFeRD-konforme Rechnungen. Seit 2025 müssen B2B-Rechnungen in Deutschland strukturierte elektronische Formate unterstützen. ZUGFeRD/Factur-X kombiniert ein visuelles PDF mit einem maschinenlesbaren XML nach EN16931.
Unsere Lösung:
- Eine Python-Lambda-Funktion generiert das PDF mit ReportLab und bettet das Factur-X-XML ein
- Die Verkäuferdaten (Firma, IBAN, USt-IdNr.) kommen aus den Payload-Firmeneinstellungen — nicht hardcoded
- Ein EPC-QR-Code (GiroCode) ermöglicht Kunden das Scannen und direkte Überweisen per Banking-App
Das Besondere: Wir konnten eine bestehende Lambda wiederverwenden und mussten nur die Seller-Daten konfigurierbar machen. Payload liefert die Daten, die Lambda generiert das PDF, S3 speichert es — alles event-driven.
Deployment: Amplify statt ECS
Ursprünglich hatten wir ECS Fargate + ALB + RDS geplant (~40€/Monat). Dann haben wir uns gefragt: Brauchen wir das wirklich für ein internes Tool?
Die Antwort war nein. Unser Setup:
- AWS Amplify für die Next.js-App (Payload CRM) — kostenlos im Free Tier
- Aurora PostgreSQL — kostenlos bis 0.5 GB
- S3 für Dokumente — minimal
- Lambda-Funktionen für PDF-Generierung — pay-per-use
Geschätzte Kosten: unter 5€/Monat statt 40€. Für ein internes Tool mit ein paar Nutzern absolut ausreichend.
Was wir gelernt haben
Payload ist mehr als ein CMS. Es ist ein Framework für datengetriebene Anwendungen. Die Kombination aus typed Collections, Hooks, Access Control und Admin Panel macht es zu einer der besten Lösungen für eigene CRM/Backendlösungen — mit dem Vorteil, dass es nativ in Next.js lebt.
Hooks ersetzen Backend-Logik. Was normalerweise Express-Middleware oder API-Handler wären, sind bei Payload deklarative Before/After-Hooks. Das reduziert Boilerplate erheblich.
Self-Hosting ist einfacher als gedacht. Mit Amplify + PostgresSQL ist ein Payload-Deployment in unter 30 Minuten live. Keine Docker-Container, keine VPCs, keine Load Balancer.
Die Community wächst schnell. Payload 3.x hat die Adoption beschleunigt. Die Discord-Community ist aktiv, die Dokumentation ist gut, und die Maintainer reagieren schnell auf Issues.
Payload CMS vs. die Alternativen: Unser Urteil nach dem Praxistest
| Kriterium | Payload CMS | Sanity | Strapi | Directus |
|---|---|---|---|---|
| TypeScript-Support | Erstklassig (native) | Gut (GROQ codegen) | Mittel (v5 besser) | Mittel |
| Next.js-Integration | Nativ (same process) | API + SDK | API | API |
| Self-Hosting | Ja (eigene Infra) | SaaS + Self-Host | Ja | Ja |
| Hooks/Lifecycle | Sehr mächtig | Webhooks | Lifecycle | Flows |
| Access Control | Granular (Feld-Level) | GROQ-basiert | Rollen | Rollen + Policies |
| Eignet sich als App-Backend | Ja | Nein (Content-fokus) | Eingeschränkt | Eingeschränkt |
| Kosten bei Skalierung | Infrastruktur only | Teuer (pro Seat) | Infrastruktur | Infrastruktur |
Für Content-Websites bleibt Sanity eine hervorragende Wahl — wir nutzen es selbst für codehero.solutions. Aber sobald ein Projekt über reines Content Management hinausgeht — CRM, E-Commerce Backend, interne Tools — hat Payload die Nase vorn.
Fazit: Payload CMS ist bereit für Production
Unser CRM läuft. Angebote werden automatisch nummeriert, Beträge berechnet, PDFs generiert und ZUGFeRD-Rechnungen erstellt. Alles TypeScript, alles in einer Next.js-App, alles auf AWS.
Payload CMS hat sich für uns als das richtige Tool erwiesen — nicht weil es perfekt ist, sondern weil es die richtige Balance zwischen Flexibilität und Struktur bietet. Es gibt uns ein professionelles Admin Panel ohne Custom-UI-Aufwand, typsichere Datenmodelle ohne ORM-Overhead und Hooks für Business-Logik ohne separates Backend.
Wenn Sie ein Projekt planen, das über eine klassische Website hinausgeht — ein Kundenportal, ein internes Tool, ein E-Commerce-Backend — lohnt sich ein Blick auf Payload CMS.
[→ Mehr über unsere Payload CMS Expertise](/payload-agentur)
[→ Projekt mit Payload CMS besprechen](/kontakt)
Haben Sie Fragen zu diesem Thema?
Wir beraten Sie gerne zu AWS, Stripe oder Ihrer individuellen Softwareentwicklung.
Kostenlose Beratung anfragen