Next.js-Entwickler in Wuppertal

Next.js für Unternehmen in Wuppertal von einer Person: Route Handler und ihr Caching, Webhooks mit Signaturprüfung, Route Handler oder Server Action, und wann ein eigener API-Dienst besser ist. Mit Hinweisen der LDI NRW.

Next.js-Entwickler

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.

Mein WordPress.org-Profil

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:

FallVerhalten
GET ohne Zusatznicht zwischengespeichert, läuft bei jeder Anfrage
GET mit export const dynamic = 'force-static'wird beim Build erzeugt und festgehalten
POST, PUT, PATCH, DELETEnie zwischengespeichert, auch nicht neben einem gecachten GET in derselben Datei
Mit aktivierten Cache ComponentsGET 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 Header X-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 wie crypto.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:

AnfrageAntwort
gültige Signatur, gültiges JSON202, danach die Zeile aus after im Log
derselbe Inhalt, dem ein Leerzeichen hinzugefügt wurde, alte Signatur401
keine Signatur401
gültige Signatur, aber kein JSON400

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.

Das Eingangsportal des Barmer Rathauses am Johannes-Rau-Platz in Wuppertal

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 HandlerServer Action
Wer ruft auf?beliebige Clients, auch fremde SystemeIhre eigene Oberfläche
Adressefrei wählbar, stabil, dokumentierbarwird vom Framework erzeugt
Methodenalle HTTP-MethodenPOST gegen die aufrufende Seite
Antwortjeder Inhaltstyp: JSON, XML, DateienRückgabewert, Cache-Aktualisierung und neu gerenderte Oberfläche in einer Antwort
Aufruf vom Clientbeliebig parallellaut Dokumentation nacheinander, pro Client eine Aktion zur Zeit
Typischer EinsatzWebhooks, Callback-Adressen, Schnittstellen für Apps und Partner, FeedsFormulare 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:

AnforderungRoute Handlereigener Dienst
Wenige Endpunkte, nur Ihre Webseite ruft sie aufjazu viel Aufwand
Webhooks, die schnell quittiert werden und kurze Arbeit auslösenjanicht nötig
Aufträge, die Minuten laufen (Import, Export, Berichte)neinja, mit Warteschlange
WebSockets oder dauerhafte Verbindungenneinja
Eine App und Partner nutzen dieselbe Schnittstellemöglichmeist besser: eigener Releasetakt und eigene Versionen
Bestehendes Backend, das Daten führtals dünne Schicht davordas 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

FrageWarum 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.

Brauchen Sie die Leistung: Next.js-Entwickler in Wuppertal?

Beschreiben Sie Ihr Projekt per E-Mail. Antwort innerhalb von 48 Stunden.

Projekt beschreiben

Weitere WordPress-Dienste und Wissensbasis entdecken