Mein Platz in der WordPress-Community
- Mein wordpress.org-Konto besteht seit 2006.
- Ich habe zum WordPress-Core in den Versionen 7.0 und 7.1 beigetragen.
- Ich betreue 30 Plugins auf wordpress.org.
- Ich organisiere WordCamps und trete dort als Speaker auf.
- Ich war bei jedem WordCamp Europe von 2017 bis 2026 dabei.
Ich bin Mariusz Szatkowski, entwickle allein von Gdynia aus und arbeite seit 2006 mit WordPress. Für Unternehmen in Wuppertal und im Bergischen Land beschreibe ich hier den Teil einer Next.js-Anwendung, der nach außen offen ist: Route Handler, also die Dateien route.ts, die Anfragen anderer Systeme entgegennehmen. Alle Angaben zu Next.js stammen aus der Dokumentation auf nextjs.org, Stand der Seiten August bis November 2026. Die Codebeispiele habe ich mit Version 16.4.6 gebaut und laufen lassen, die laut npm-Registry am 9. November 2026 erschien.
Was ein Route Handler ist
Ein Route Handler ist laut Dokumentation eine route.ts im Ordner app, die die Web-APIs Request und Response benutzt. Die Funktionen heißen wie die HTTP-Methoden: GET, POST, PUT, PATCH, DELETE, HEAD und OPTIONS. Ruft jemand eine Methode auf, die nicht definiert ist, antwortet Next.js mit 405. OPTIONS ergänzt Next.js selbst, wenn Sie es nicht schreiben. In meinem Test lieferte GET auf einen Handler, der nur POST kennt, die 405, und OPTIONS kam mit dem Header allow: OPTIONS, POST zurück.
Zwei Eigenschaften sind für die Planung wichtig. Eine route.ts darf nicht auf derselben Ebene liegen wie eine page.tsx, weil jede der beiden Dateien alle HTTP-Verben dieser Adresse übernimmt. Und ein Route Handler nimmt an Layouts und Navigation im Browser nicht teil: Er ist ein Endpunkt, keine Seite.
Der Leitfaden zum Backend for Frontend sagt dazu zwei Dinge, die ich bei jedem Projekt ernst nehme. Route Handler sind öffentliche Endpunkte, jeder Client kann sie aufrufen. Und die Backend-Funktionen von Next.js sind nach der Dokumentation kein vollständiger Backend-Ersatz, sondern eine API-Schicht, die öffentlich erreichbar ist, jede HTTP-Anfrage verarbeitet und jeden Inhaltstyp liefern kann.
Was ein Route Handler zwischenspeichert
Hier gibt es eine häufige Fehlannahme aus der Zeit von Next.js 13 und 14. Laut Versionstabelle in der Referenz zu route.js wurde mit 15.0.0-RC das Standardverhalten von GET von statisch auf dynamisch geändert. Heute gilt:
| Fall | Verhalten |
|---|---|
GET ohne Zusatz | nicht zwischengespeichert, läuft bei jeder Anfrage |
GET mit export const dynamic = 'force-static' | wird beim Build erzeugt und festgehalten |
POST, PUT, PATCH, DELETE | nie zwischengespeichert, auch nicht neben einem gecachten GET in derselben Datei |
| Mit aktivierten Cache Components | GET verhält sich wie eine normale Seite: läuft zur Anfragezeit, wird vorgerendert, wenn nichts Dynamisches gelesen wird, und use cache hält Daten fest |
Ich habe die beiden ersten Zeilen geprüft. Zwei Handler, beide geben Date.now() zurück, der zweite mit force-static. Zwei Aufrufe im Abstand von einer Sekunde ergaben beim ersten Handler zwei verschiedene Zeiten, beim zweiten zweimal dieselbe. Im Build-Manifest tauchte nur der statische Handler als vorgerendert auf.
Bei aktivierten Cache Components nennt die Dokumentation zwei Stolperstellen. Das Vorrendern endet, sobald der Handler Netzwerk, Datenbank, Dateisystem, headers(), cookies() oder Eigenschaften des Request-Objekts wie request.url anfasst. Und use cache darf nicht direkt im Rumpf des Handlers stehen, sondern gehört in eine Hilfsfunktion.
Der dritte Punkt betrifft Ihren Betrieb. Setzt ein Handler Cache-Control: public mit max-age oder s-maxage, kann ein CDN die Antwort halten und spätere Anfragen auf dieselbe Adresse beantworten, ohne den Handler aufzurufen. Dann laufen weder die Berechtigungsprüfung noch ein Limit. Die Dokumentation rät deshalb, nur Antworten zu cachen, die jeder mit der Adresse sehen darf. Welche Header ein CDN liest und was er in den Cache-Schlüssel nimmt, hängt vom Anbieter ab.
Webhooks fremder Systeme annehmen
Ein Warenwirtschaftssystem, ein Zahlungsdienst oder ein Versanddienstleister meldet Ereignisse an eine feste Adresse Ihrer Anwendung. Als Beispiel nehme ich Bestellungen, die ein Shop an Ihre Next.js-Anwendung meldet. Die Next.js-Dokumentation zeigt den Handler im Kern so: Body mit request.text() lesen, verarbeiten, 200 zurückgeben. Eine Prüfung, von wem die Anfrage kommt, fehlt in diesem Beispiel. Die Adresse ist öffentlich, jeder kann dorthin posten.
Üblich ist eine Signatur. Ich nehme als Vorlage die Beschreibung von GitHub, weil sie genau dokumentiert ist. Andere Absender nennen ihre Header anders und signieren teils anders, deshalb lese ich bei jedem Projekt die Dokumentation des Absenders. Das Verfahren bei GitHub:
- Das gemeinsame Geheimnis liegt auf Ihrem Server, nicht im Code und nicht im Repository.
- Der Absender bildet einen HMAC mit SHA-256 über den Body und schickt ihn als
sha256=und Hexwert im HeaderX-Hub-Signature-256. - Sie berechnen denselben Wert über denselben Body und vergleichen. Ein einfaches
==ist laut GitHub falsch, empfohlen ist ein Vergleich in konstanter Zeit wiecrypto.timingSafeEqual. - Der Body wird als UTF-8 behandelt.
// lib/signature.ts
import { createHmac, timingSafeEqual } from 'node:crypto'
export function isValidSignature(rawBody: string, header: string | null, secret: string) {
if (!header?.startsWith('sha256=')) return false
const expected = Buffer.from(
'sha256=' + createHmac('sha256', secret).update(rawBody, 'utf8').digest('hex')
)
const received = Buffer.from(header)
return received.length === expected.length && timingSafeEqual(received, expected)
}Die Längenprüfung steht vor timingSafeEqual, weil diese Funktion bei ungleich langen Puffern einen Fehler wirft. Der Handler selbst:
// app/api/webhooks/orders/route.ts
import { after } from 'next/server'
import { isValidSignature } from '@/lib/signature'
export async function POST(request: Request) {
const rawBody = await request.text()
const signature = request.headers.get('x-hub-signature-256')
if (!isValidSignature(rawBody, signature, process.env.WEBHOOK_SECRET!)) {
return new Response(null, { status: 401 })
}
let event: unknown
try {
event = JSON.parse(rawBody)
} catch {
return new Response(null, { status: 400 })
}
const deliveryId = request.headers.get('x-github-delivery')
after(async () => {
// hier die eigentliche Arbeit: Bestellung speichern, Mail auslösen
console.log('verarbeitet', deliveryId)
})
return new Response(null, { status: 202 })
}Ich habe das mit Next.js 16.4.6 gebaut und gegen den Testwert aus der GitHub-Dokumentation geprüft (Geheimnis und Nutzlast stehen dort, die Signatur ebenfalls). Ergebnisse:
| Anfrage | Antwort |
|---|---|
| gültige Signatur, gültiges JSON | 202, danach die Zeile aus after im Log |
| derselbe Inhalt, dem ein Leerzeichen hinzugefügt wurde, alte Signatur | 401 |
| keine Signatur | 401 |
| gültige Signatur, aber kein JSON | 400 |
Die Reihenfolge ist Absicht. Zuerst Rohtext lesen und Signatur prüfen, dann erst parsen. Wer request.json() aufruft und das Ergebnis wieder in Text verwandelt, verändert Leerzeichen und Feldreihenfolge, und eine gültige Lieferung fällt durch. Aus einem Handler ohne try um JSON.parse wurde in meinem ersten Durchlauf bei einem Body ohne JSON ein 500, obwohl die Signatur stimmte. Ein signierter, aber kaputter Body ist ein 400, kein Serverfehler.
Schnell antworten, danach arbeiten
GitHub verlangt in den Hinweisen zu Webhooks eine 2XX-Antwort binnen 10 Sekunden und rät, Nutzlasten über eine Warteschlange asynchron zu verarbeiten. Andere Absender haben andere Fristen. Für Next.js gibt es dafür after: Der Callback läuft, wenn die Antwort fertig ist, auch wenn die Antwort mit einem Fehler endet. Die Dauer ist begrenzt durch das Maximum Ihrer Plattform für die Route, das sich laut Dokumentation mit maxDuration einstellen lässt, wenn die Plattform das unterstützt.
Zwei Folgen daraus. Erstens ist after kein Ersatz für eine Warteschlange. Reißt die Verarbeitung ab, ist die Lieferung bestätigt und der Auftrag verloren. Was nicht verloren gehen darf, schreibe ich zuerst in die Datenbank und verarbeite es von dort aus. Zweitens kommen Lieferungen doppelt an. Laut GitHub bleibt die Kennung X-GitHub-Delivery bei einer erneuten Zustellung gleich, und GitHub empfiehlt, sie gegen Wiederholungen zu nutzen. Ich speichere die Kennung mit einer Eindeutigkeitsregel in der Tabelle. Ein Merker im Arbeitsspeicher des Handlers reicht nicht: Die Dokumentation weist darauf hin, dass manche Hosts Route Handler als Lambda-Funktionen betreiben und diese keine Daten zwischen Anfragen teilen.

Foto: wnwtal, Public domain, Wikimedia Commons.
Route Handler oder Server Action?
Beide laufen auf dem Server und beide sind von außen erreichbar. Sie lösen verschiedene Aufgaben.
| Route Handler | Server Action | |
|---|---|---|
| Wer ruft auf? | beliebige Clients, auch fremde Systeme | Ihre eigene Oberfläche |
| Adresse | frei wählbar, stabil, dokumentierbar | wird vom Framework erzeugt |
| Methoden | alle HTTP-Methoden | POST gegen die aufrufende Seite |
| Antwort | jeder Inhaltstyp: JSON, XML, Dateien | Rückgabewert, Cache-Aktualisierung und neu gerenderte Oberfläche in einer Antwort |
| Aufruf vom Client | beliebig parallel | laut Dokumentation nacheinander, pro Client eine Aktion zur Zeit |
| Typischer Einsatz | Webhooks, Callback-Adressen, Schnittstellen für Apps und Partner, Feeds | Formulare und Änderungen in Ihrer Anwendung |
Die Dokumentation zu Server Actions nennt die Reihenfolge ausdrücklich: Der Client schickt Aktionen nacheinander, sodass der neu gerenderte Baum zu dem Ergebnis passt, das ihn ausgelöst hat. Für parallele Abrufe verweist sie auf Server Components oder einen Route Handler für Anfragen ohne Änderung. Die Server-Seite stellt die Aktionen laut Dokumentation nicht in eine Warteschlange, die Reihenfolge gilt nur für den Versand vom Client.
Für Seiten Ihrer eigenen Anwendung gilt eine dritte Regel der Dokumentation: Daten holt eine Server Component direkt aus der Quelle, nicht über einen eigenen Route Handler. Wird die Seite beim Build vorgerendert, schlägt der Build fehl, weil dabei kein Server auf Anfragen wartet. Läuft die Seite bei Bedarf, kostet der Umweg eine zusätzliche HTTP-Runde. Wer die Sicherheit von Server Actions prüfen lassen will, findet das Vorgehen auf der Seite zu Next.js in Bonn.
Wann ein eigener API-Dienst besser ist
Ein Route Handler ist praktisch, solange die Schnittstelle zur Webseite gehört. Die Dokumentation nennt unter den Hinweisen zur Betriebsumgebung vier Grenzen, wenn der Host Route Handler als Lambda-Funktionen ausführt: kein Datenaustausch zwischen Anfragen, möglicherweise kein Schreibzugriff auf das Dateisystem, Abbruch lang laufender Handler durch Zeitlimits und keine WebSockets. Hinzu kommt der Hinweis zum Begrenzen von Anfragen: Ein Zähler im Arbeitsspeicher gilt je Serverinstanz und beginnt bei einem Neustart von vorn. Läuft die Anwendung auf mehr als einer Instanz, gehören die Zähler in einen gemeinsamen Speicher oder ins Limit des Hosts.
Aus diesen Grenzen und meiner Erfahrung ergibt sich diese Faustregel. Sie ist meine Einschätzung, kein Zitat:
| Anforderung | Route Handler | eigener Dienst |
|---|---|---|
| Wenige Endpunkte, nur Ihre Webseite ruft sie auf | ja | zu viel Aufwand |
| Webhooks, die schnell quittiert werden und kurze Arbeit auslösen | ja | nicht nötig |
| Aufträge, die Minuten laufen (Import, Export, Berichte) | nein | ja, mit Warteschlange |
| WebSockets oder dauerhafte Verbindungen | nein | ja |
| Eine App und Partner nutzen dieselbe Schnittstelle | möglich | meist besser: eigener Releasetakt und eigene Versionen |
| Bestehendes Backend, das Daten führt | als dünne Schicht davor | das Backend bleibt, wo es ist |
Der letzte Fall kommt in Wuppertal und anderswo am häufigsten vor: Ein Laravel- oder Symfony-Backend, ein ERP oder ein WordPress führt die Daten, und Next.js zeigt sie an. Die Dokumentation beschreibt dafür einen Route Handler als Vermittler, der nur feste Endpunkte durchreicht, die Anfrage prüft, das Backend mit einem serverseitigen Token aufruft und die Antwort umformt. Der Pfad zum Backend kommt aus einer festen Liste, nicht aus der URL des Aufrufers, sodass niemand Anfrage oder Token an ein anderes Ziel lenken kann. Auch Header will die Dokumentation nicht blind weiterreichen, weil sonst Cookie und Authorization des Nutzers mitwandern. Für das PHP-Backend dahinter gibt es die Seite zur PHP-Entwicklung in Wuppertal.
Datenschutz: was in einer Webhook-Lieferung steckt
Eine Bestell-Lieferung enthält Namen, Adressen und oft E-Mail-Adressen. Zuständig für Unternehmen in Wuppertal ist die Landesbeauftragte für Datenschutz und Informationsfreiheit Nordrhein-Westfalen (LDI NRW). Drei Punkte, die für den Aufbau zählen:
- Integrität. Art. 32 Abs. 1 DS-GVO verlangt geeignete technische und organisatorische Maßnahmen, die unter anderem die Vertraulichkeit und Integrität der Systeme sicherstellen. Die Signaturprüfung ist eine solche Maßnahme für die Frage, ob eine Lieferung vom erwarteten Absender stammt und unterwegs nicht verändert wurde. Sie ersetzt keine weiteren Maßnahmen.
- Drittländer. Die LDI NRW erklärt auf ihrer Seite zu den allgemeinen Grundsätzen, dass auch Datenzugriffe aus einem Drittland für Backups, Wartung und Servicefunktionen Übermittlungen sein können. Eine Übermittlung wird in zwei Stufen geprüft: zuerst die allgemeinen Vorgaben der DS-GVO, dann die Bedingungen von Kapitel V. Läuft Ihr Webhook-Absender oder Ihr API-Dienst bei einem Anbieter mit Sitz oder Zugriff in einem Drittland, gehört das in diese Prüfung. Für die USA verweist die LDI NRW auf ihrer Seite zum Angemessenheitsbeschluss auf den Beschluss zum EU-U.S. Data Privacy Framework vom 10. Juli 2023, der nur für teilnehmende US-Unternehmen gilt.
- Auftragsverarbeitung. Ob ein Anbieter Auftragsverarbeiter ist, entscheidet sich nach dem Einzelfall. Ich liefere die technische Beschreibung, welche Daten in welche Richtung fließen, und Ihre Rechtsberatung oder Ihr Datenschutzbeauftragter bewertet sie. Das ist keine Rechtsberatung.
Wer Lieferungen protokolliert, findet die Regeln für das Log auf der Seite zu Next.js in Essen.
Checkliste für Ihre Schnittstelle
| Frage | Warum sie zählt |
|---|---|
| Ruft nur Ihre Seite den Endpunkt auf, oder auch ein Fremdsystem? | Bestimmt Route Handler oder Server Action |
| Prüft der Handler die Signatur über den Rohtext, bevor er parst? | Sonst fällt Gültiges durch oder Ungültiges durch |
| Liegt das Geheimnis nur auf dem Server, und weiß jemand, wie es getauscht wird? | Ein Geheimnis ohne Plan zum Tausch bleibt ewig |
| Antwortet der Handler innerhalb der Frist des Absenders? | Sonst gilt die Lieferung als fehlgeschlagen |
| Wird eine Lieferkennung mit Eindeutigkeitsregel gespeichert? | Doppelte Zustellungen sind normal |
Geht nichts verloren, wenn after abbricht? | Erst speichern, dann verarbeiten |
Hat ein gecachtes GET einen Grund, öffentlich zu sein? | Ein CDN umgeht Prüfung und Limit |
| Liegt ein Limit in einem gemeinsamen Speicher oder beim Host? | Zähler im Arbeitsspeicher gelten je Instanz |
| Läuft der Host Route Handler als Lambda-Funktionen? | Dann gelten Zeitlimits, kein WebSocket |
| Ist geklärt, wohin die Daten der Lieferung fließen? | Drittlandzugriff gehört in die Prüfung |
So läuft ein Projekt mit mir
Ich arbeite aus der Ferne und schriftlich, ohne Termine und Telefonate. Zum Start genügt eine Mail mit Adresse, Ziel und Frist. Danach lese ich den Code und stelle meine Fragen schriftlich. Sie bekommen eine Beschreibung des Umfangs mit den Annahmen, gebaut wird auf einer Staging-Umgebung, und Sie geben schriftlich frei, bevor etwas live geht. Für dieses Thema liefere ich die Handler mit Signaturprüfung, die Regeln zu Lieferkennungen und Wiederholungen, eine Liste der Umgebungsvariablen und eine Beschreibung der Datenflüsse für Ihr Verzeichnis der Verarbeitungstätigkeiten. Gestaltung und Vorlagen für Oberflächen bringen Sie mit, ich setze sie um.
Läuft die Anwendung später weiter, beschreibt die Seite zur Wartung in Wuppertal die Betreuung mit getesteten Updates und monatlichem Bericht. Besteht Ihre Anwendung hauptsächlich aus Inhalten, prüfe ich vorab, ob Astro weniger Betrieb bedeutet. Für den Weg zwischen beiden gibt es die Seite zur Migration zwischen Next.js und Astro in Wuppertal.
Häufige Fragen
Wird ein Route Handler zwischengespeichert? Standardmäßig nicht. Nur GET lässt sich festhalten, etwa mit export const dynamic = ‘force-static’, alle anderen Methoden bleiben ungecacht. Seit 15.0.0-RC ist GET dynamisch statt statisch. Wer einen CDN davor hat und Cache-Control public setzt, kann Antworten dort festhalten, und dann laufen weder die Prüfung im Handler noch ein Limit.
Warum muss ich den Body als Text lesen, bevor ich die Signatur prüfe? Die Signatur wird über die Bytes des Bodys gebildet. Wer ihn erst mit request.json() parst und wieder in Text verwandelt, ändert Leerzeichen und Reihenfolge, und die Prüfung schlägt fehl. In meinem Test wurde derselbe Inhalt mit einem zusätzlichen Leerzeichen mit 401 abgewiesen.
Soll ich Webhooks mit einer Server Action annehmen? Nein. Eine Server Action ist für Änderungen aus Ihrer eigenen Oberfläche gedacht und läuft als POST gegen die Seite, die sie aufruft. Ein fremdes System braucht eine feste, dokumentierte Adresse mit eigener Authentifizierung. Das ist ein Route Handler.
Was passiert, wenn der Absender dieselbe Lieferung zweimal schickt? Das kommt vor, etwa nach einem Zeitüberschreitungsfehler. GitHub etwa behält bei einer erneuten Zustellung dieselbe Lieferkennung. Ich speichere die Kennung mit einer Eindeutigkeitsregel in der Datenbank, denn ein Speicher im Handler reicht auf Hosts mit Lambda-Funktionen nicht.
Wann lohnt sich ein eigener API-Dienst neben Next.js? Wenn mehr als Ihre Webseite die Schnittstelle nutzt, wenn Aufträge lange laufen, wenn WebSockets nötig sind oder wenn die Schnittstelle einen eigenen Takt für Releases braucht. Die Next.js-Dokumentation nennt ihre Backend-Funktionen selbst keinen vollständigen Backend-Ersatz.
Gestalten Sie auch die Oberflächen dazu? Nein. Gestaltung, Mockups und Wireframes bringen Sie oder Ihre Agentur mit. Ich baue die Schnittstellen und setze die Vorlage um.
Ihre Schnittstelle in einer E-Mail
Wenn ein Fremdsystem Ihre Anwendung anruft oder Sie wissen wollen, ob Ihre Schnittstelle mit einem Route Handler gut aufgehoben ist, schreiben Sie mir über das Kontaktformular. Schicken Sie die Adresse der Anwendung, den Absender der Webhooks, Ihr Ziel, den Wunschtermin und Ihr Hosting. Ich antworte an Werktagen schriftlich mit meinen Fragen, und die erste schriftliche Schätzung ist kostenlos.
Ausgewählte Projekte
Beispiele aus meiner Arbeit.
Corporate Website: osemka.pl - Banner
Ein Paket verschiedener Sonderbanner für die Website osemka.pl
Customer-Experience-Plattform: QUALITY WATCH
QUALITY WATCH ist eine Plattform für Customer Experience und Servicequalität, die Mystery Shopping, Service-Audits, Customer-Journey-Arbeit und B2B-Beratung präsentiert.
dkf.za.pl - WordPress Projekt | WPPoland
DKF.za.pl ist eine im Jahr 2010 erstellte Website für den Diskussionsfilmklub „ZA“, der als Teil der Polnischen Föderation der Diskussionsfilmklubs tätig ist...
WordPress Support & Entwicklung in Wuppertal
Brauchen Sie die Leistung: Next.js-Entwickler in Wuppertal?
Beschreiben Sie Ihr Projekt per E-Mail. Antwort innerhalb von 48 Stunden.
Projekt beschreibenWeitere WordPress-Dienste und Wissensbasis entdecken
Migration zu Astro, Next.js und Headless WordPress.
WooCommerce-Synchronisierung mit ERP und Großhandel.
Geschäftsprozessautomatisierung rund um WordPress und Firmensysteme.
Bibliothek konkreter Automatisierungsfälle.
Headless WordPress, Sanity, Strapi und Contentful mit Astro oder Next.js.
Astro, MDX, Edge Delivery und an echtem Traffic gemessene Core Web Vitals.
Individuelle WordPress-Entwicklung und Architektur.
Skalierbare Headless-, ERP- und KI-Architektur für Enterprise.
Verwandte Kategorien
Unterstützende Artikel

Sechs bis sechzehn Wochen für typische Projekte, in vier Phasen: Analyse, Scoping, Build und Umstellung, Tuning. Die Variablen sind Katalogumfang, Anzahl der Integrationen, URL-Erhalt und die Bereitschaft des Redaktionsteams, nicht die Wahl des Frameworks.

Umfassende 4-Jahres-TCO-Analyse (Total Cost of Ownership), reale Core-Web-Vitals-Benchmarks, Astro 7 GraphQL APQ-Architektur und eine 10-Punkte-Entscheidungsmatrix für Enterprise-Entscheider zwischen entkoppeltem und traditionellem WordPress.

Die Entscheidung Shopify Plus vs WooCommerce headless im Jahr 2026 ist kein binärer "Plattform vs Custom"-Kompromiss mehr. Beide laufen headless, beide integrieren KI, beide liefern am Edge aus. Die echten Achsen sind Kontrolle, Gesamtkosten über fünf Jahre und Exit-Strategie. Dieser Artikel durchläuft die Entscheidungsmatrix mit bestätigten Plattformfakten.