Astro-Entwickler in Wuppertal

Astro-Entwickler für Wuppertal: Anfrageformulare mit Astro Actions und Zod, Seiten bei Anfrage rendern, Spamschutz ohne Tracker. Remote aus Gdynia, schriftlich.

Astro-Entwickler

Migration von WordPress zu Astro in Wuppertal

Viele Unternehmen in Wuppertal nutzen WordPress, stoßen aber an Grenzen bei Performance, Sicherheit und Hosting-Kosten. Astro löst diese Probleme mit statischem HTML, null JavaScript und Edge-Deployment. Ich migriere bestehende WordPress-Seiten zu Astro mit vollständiger SEO-Erhaltung, URL-Mapping und 301-Weiterleitungen.

  • PageSpeed 95-100

    Statisches HTML ohne JavaScript. Schneller als jede WordPress-Lösung.

  • SEO-sichere Migration

    URL-Mapping, 301-Weiterleitungen, Google-Rankings erhalten.

  • Hosting auf Cloudflare Pages

    Globales CDN, kostenloses SSL, sofortige Deployments. Hosting-Kosten nahe null.

#Formulare in Astro: wann eine Seite einen Server braucht

Ich bin Mariusz Szatkowski, arbeite seit 2006 mit WordPress und baue Websites heute auch mit Astro. Ich sitze in Gdynia, arbeite vollständig remote und schriftlich, Meetings und Telefonate gibt es nicht. Diese Seite richtet sich an Unternehmen in Wuppertal und im Bergischen Land, deren Website ein Anfrageformular hat und die wissen wollen, was dahinter passiert.

Mein Thema ist die Serverseite eines Formulars: Astro Actions, die Prüfung der Eingaben mit Zod, Seiten, die bei Anfrage gerendert werden, und ein Spamschutz ohne Tracker von Drittanbietern. Alles, was ich zu Astro schreibe, stammt aus der Dokumentation zu Actions und der Seite zum Rendern bei Anfrage.

Die Wirtschaftsförderung Wuppertal nennt auf ihrer Standortseite als Kompetenzfelder Automotive, Chemie, Health Care, technische Textilien sowie Maschinen- und Werkzeugbau. Ich leite daraus eine Vermutung ab, keine Tatsache über einzelne Firmen: Auf solchen Websites sind Produktseiten und Datenblätter meist statisch, aber dazu gehören oft Formulare, etwa Händleranfrage, Musteranfrage oder Bewerbung. Nur diese kleinen Teile brauchen Servercode.

Campus Grifflenberg der Bergischen Universität Wuppertal

Foto: Im Fokus, CC BY-SA 4.0, Wikimedia Commons.

#Statische Seite, Adapter und Rendern bei Anfrage

Astro rendert nach der Dokumentation standardmäßig jede Seite beim Build zu statischem HTML. Eine Seite, die bei Anfrage vom Server erzeugt wird, braucht zwei Dinge:

  1. Einen Adapter für die Laufzeit, auf der der Code läuft. Astro pflegt offizielle Adapter für Node.js, Netlify, Vercel und Cloudflare.
  2. export const prerender = false an der einzelnen Seite oder dem Endpunkt. Der Rest der Website bleibt statisch.

Die Dokumentation rät, mit dem statischen Modus zu beginnen, bis die meisten Seiten wirklich auf Anfrage entstehen. Der Modus output: 'server' bringt laut Dokumentation keine zusätzlichen Funktionen, er dreht nur den Standard um. Für eine Firmenwebsite mit einem Formular bleibt also fast alles statisch, und nur die Kontaktseite bekommt Servercode.

Zwei Adapter erkläre ich Kunden am häufigsten, beide nach ihren Dokumentationsseiten:

  • @astrojs/node baut im Modus standalone einen Server, der beim Start des Einstiegsmoduls selbst läuft. Im Modus middleware lässt er sich in einen anderen Node.js-Server wie Express oder Fastify einhängen, der dann auch die statischen Dateien ausliefern muss.
  • @astrojs/cloudflare erzeugt Worker-Code. Umgebungsvariablen und Bindings stehen laut Dokumentation in der Datei wrangler.jsonc.

Welcher passt, hängt an Ihrem Hosting und Ihrer Datenschutzprüfung, nicht an Astro. Das klären wir schriftlich vor dem Start.

#Eine Action für ein Anfrageformular

Eine Action ist laut Dokumentation eine typsichere Backend-Funktion. Sie kümmert sich um das Lesen der Daten und die Eingabeprüfung mit Zod, und sie vereinheitlicht Fehler über ActionError. Actions gibt es seit Astro 4.15. Stand 11. November 2026 ist laut npm-Registry Astro 7.4.11 die aktuelle Version, und Ihr Projekt bekommt eine feste Version, die ich im Umfang festhalte.

Ein Anfrageformular mit vier Feldern, nach dem Muster der Dokumentation:

// src/actions/index.ts
import { defineAction } from 'astro:actions';
import { z } from 'astro/zod';

export const server = {
  anfrage: defineAction({
    accept: 'form',
    input: z.object({
      name: z.string().min(2).max(120),
      email: z.email(),
      nachricht: z.string().min(10).max(4000),
      firma_website: z.string().nullish(), // Köderfeld, siehe unten
    }),
    handler: async (input) => {
      if (input.firma_website) return { ok: true }; // stillschweigend verwerfen
      // hier: E-Mail oder CRM beauftragen
      return { ok: true };
    },
  }),
};

Drei Punkte aus der Dokumentation, die in der Praxis zählen:

  • accept: 'form' ist nötig, weil Actions sonst JSON erwarten.
  • Leere Felder kommen als null an. Wird ein Textfeld leer abgeschickt, ist der Wert laut Dokumentation null, nicht "". Deshalb steht beim Köderfeld nullish().
  • Bei ungültiger Eingabe liefert die Action den Fehler BAD_REQUEST, und der Handler läuft gar nicht erst an.

Was der Handler mit der Anfrage macht (Mail, CRM, Ticket), ist eine eigene Entscheidung. Ich lege sie im schriftlichen Umfang fest, weil daran der Datenschutz hängt.

#Das Formular auch ohne JavaScript

Eine Action lässt sich aus einem normalen HTML-Formular aufrufen: method="POST" und action={actions.anfrage}. Das funktioniert laut Dokumentation ohne Client-JavaScript und ist ein Rückfall, wenn Skripte nicht laden. Die Seite muss dafür auf Anfrage gerendert werden.

---
import { actions, isInputError } from 'astro:actions';
export const prerender = false;

const result = Astro.getActionResult(actions.anfrage);
const fehler = isInputError(result?.error) ? result.error.fields : {};
---
<form method="POST" action={actions.anfrage}>
  <label for="email">E-Mail</label>
  <input id="email" type="email" name="email" required aria-describedby="email-fehler" />
  {fehler.email && <p id="email-fehler">{fehler.email.join(', ')}</p>}
  <!-- weitere Felder -->
  <button>Anfrage senden</button>
</form>

Astro.getActionResult() liefert auf dem Server data oder error, oder undefined, wenn die Action in dieser Anfrage nicht lief. isInputError() trennt Eingabefehler von anderen Fehlern, und fields enthält die Meldungen pro Feldname. Die Verbindung zwischen Eingabefeld und Fehlertext über aria-describedby übernehme ich aus dem Beispiel der Dokumentation.

Zwei Eigenheiten, die ich vor dem Start nenne:

  • Eingaben werden nach dem Absenden geleert. Die Dokumentation beschreibt dafür transition:persist mit View Transitions.
  • Das Ergebnis gilt nur für diese POST-Anfrage. Beim Neuladen erscheint die Rückfrage, ob das Formular erneut gesendet werden soll. Wer das nicht will, setzt laut Dokumentation das Muster POST, Redirect, GET in einer Middleware um, mit Cookie oder Session-Speicher.

#Spamschutz ohne Tracker

Jedes öffentliche Formular zieht automatisierte Anfragen an. Mein Vorgehen in dieser Reihenfolge, von billig zu aufwendig:

  1. Serverseitige Grenzen. Die Zod-Schemas begrenzen Länge und Form jedes Feldes. Das ist Spamschutz und Datensparsamkeit zugleich.
  2. Köderfeld. Ein für Menschen unsichtbares Feld, das nur Skripte ausfüllen. Es hält einfache Bots auf, mehr nicht, und ich verkaufe es nicht als vollständigen Schutz.
  3. Ratenbegrenzung. Die Dokumentation empfiehlt, Berechtigung und Ratenbegrenzung pro Action im Handler zu prüfen. Wo ich sie setze (Handler oder Hosting), hängt vom Adapter ab.
  4. Eine Rätselprüfung ohne Fremddienst. ALTCHA ist ein MIT-lizenziertes Projekt, das sich nach eigener Beschreibung selbst betreiben lässt, per Proof-of-Work arbeitet und ohne Cookies und Fingerprinting auskommt. Das sind Angaben des Projekts. Ich prüfe sie im Browser, bevor ich sie auf Ihrer Seite als zutreffend behandle.

Ein Fremddienst als Spamschutz lädt Skripte und überträgt Besucherdaten an Dritte. Dann gehört er auf die Liste der Fremddienste im Datenschutz. Wo der Schutz auf Ihrem eigenen Server läuft, entfällt diese Zeile.

#Eine Action ist ein öffentlicher Endpunkt

Die Dokumentation sagt es ausdrücklich: Actions sind unter einem Pfad wie /_actions/blog.like öffentlich erreichbar. Deshalb gelten dieselben Prüfungen wie für jede Schnittstelle. Zwei Folgerungen:

  • Berechtigung im Handler. Geschützte Aktionen prüfen den Nutzer im Handler und werfen sonst ActionError mit dem Code UNAUTHORIZED. Ein Kontaktformular braucht das nicht, ein Händlerbereich schon.
  • Herkunftsprüfung. Astro prüft bei Seiten, die auf Anfrage gerendert werden, standardmäßig, ob Formulare aus derselben Herkunft kommen (security.checkOrigin, Standard true). Laut Konfigurationsreferenz nutzt Astro dafür Sec-Fetch-Site und fällt auf Origin zurück. Eine fremde Herkunft erhält Status 403. Ich lasse die Einstellung an und schreibe es in den Umfang, falls sie aus einem Grund abgeschaltet werden muss.

#Datenschutz: was ein Formular nach NRW-Recht auslöst

Zuständig für Unternehmen in Wuppertal ist die Landesbeauftragte für Datenschutz und Informationsfreiheit Nordrhein-Westfalen (LDI NRW). Ich bin Entwickler, die rechtliche Bewertung gehört zu Ihrer Rechtsberatung. Folgende drei Aussagen sind für den Aufbau nützlich:

  • Datenschutzerklärung ergänzen. Die LDI NRW schreibt in ihrem Muster für Datenschutzhinweise, dass die Erklärung zu ergänzen ist, wenn die Website unter anderem ein Kontaktformular anbietet.
  • Datenminimierung und Speicherbegrenzung. Nach Art. 5 Abs. 1 Buchst. c und e DSGVO müssen Daten auf das notwendige Maß beschränkt sein und dürfen nur so lange identifizierbar bleiben, wie es der Zweck erfordert. Für ein Formular heißt das: nur Felder, die Sie für die Antwort brauchen, und eine Aufbewahrungsfrist für Anfragen.
  • Zugriff auf das Endgerät. § 25 TDDDG verlangt für Speicherung und Zugriff auf Informationen im Endgerät grundsätzlich eine Einwilligung, mit der Ausnahme, dass beides unbedingt erforderlich ist, um einen ausdrücklich gewünschten digitalen Dienst bereitzustellen. Ein Formular mit Köderfeld und serverseitiger Prüfung speichert nichts im Browser. Bei jedem Spamschutz schaue ich nach, ob er etwas ablegt, und trage das Ergebnis in die Liste ein.

#Checkliste für Ihr Formular

FrageFolge
Gibt es überhaupt Servercode auf der Seite?Ohne Anfrage-Rendering reicht eine statische Seite, Formular über einen externen Dienst oder ein CMS
Welche Seite muss auf Anfrage rendern?Nur diese, mit prerender = false, dazu ein Adapter
Wohin gehen die Daten?Mail, CRM, Ticketsystem: im Umfang festgelegt und in der Datenschutzerklärung genannt
Welche Felder sind Pflicht?Nur was für die Antwort nötig ist, jedes mit Längengrenze im Schema
Wie lange bleiben Anfragen gespeichert?Eine Frist, die Sie festlegen
Läuft das Formular ohne JavaScript?Ja, über method="POST" und action={actions.name}
Welcher Spamschutz?Grenzen, Köderfeld, Ratenbegrenzung, bei Bedarf selbst betriebene Rätselprüfung
Lädt der Spamschutz etwas von Dritten?Wenn ja, auf die Liste der Fremddienste
Wo laufen Server und Daten?Adapter und Hosting, mit Standort, im schriftlichen Umfang

#So läuft ein Projekt mit mir

Alles ist schriftlich.

  1. Briefing. Sie senden mir die Adresse Ihrer Website, das Ziel, den Termin und den aktuellen Stack. Ich frage schriftlich nach, was fehlt.
  2. Umfang und Annahmen. Ich halte fest, welche Formulare es gibt, wohin die Daten gehen, welcher Adapter und welches Hosting vorgesehen sind und was ich von Ihnen voraussetze. Layout, Grafik und Wireframes kommen von Ihnen, ich setze sie technisch um. Gestartet wird erst, wenn Sie den Umfang schriftlich bestätigt haben.
  3. Aufbau auf einer Testumgebung. Sie sehen den Stand auf einer Vorschau-Adresse und können das Formular selbst absenden.
  4. Abnahme. Sie nehmen anhand des schriftlichen Umfangs ab. Änderungen außerhalb davon erfasse ich als neues Angebot.
  5. Start und Wartung (optional). Nach dem Start kann ich Updates und Abhängigkeiten übernehmen. Wie das abläuft, steht auf der Seite Wartung und Support in Wuppertal. Stunden daraus gelten für den jeweiligen Monat.

Besteht Ihre Seite hauptsächlich aus einer Anwendung mit Anmeldung und Datenbank, ist Next.js in Wuppertal oft die bessere Wahl. Läuft Ihre Seite auf WordPress und soll es bleiben, hilft die Seite zu WordPress in Wuppertal.

#Häufige Fragen

#Brauche ich für ein Kontaktformular in Astro einen Server?

Eine Action ist Servercode und braucht deshalb eine Seite, die auf Anfrage gerendert wird, also einen Adapter. Alternativ bleibt die Seite statisch und das Formular geht an einen externen Dienst. Das ist dann ein Fremddienst im Datenschutz. Ich lege die Variante im Umfang fest.

#Was passiert, wenn jemand das Formular ohne JavaScript abschickt?

Bei einem Formular mit method="POST" und action={actions.name} läuft die Action auf dem Server, und Fehler lassen sich mit Astro.getActionResult() in der Seite anzeigen. Das nennt die Dokumentation einen Rückfall, falls JavaScript nicht lädt.

#Wie schützen Sie das Formular vor Spam, ohne Google reCAPTCHA?

Mit Grenzen im Schema, einem Köderfeld und einer Ratenbegrenzung. Reicht das nicht, kommt eine selbst betriebene Rätselprüfung wie ALTCHA infrage. Ein einzelnes Mittel schützt nicht vollständig, deshalb kombiniere ich sie.

#Darf ich Anfragen aus dem Formular einfach speichern?

Das beurteilt Ihre Rechtsberatung. Technisch halte ich fest, welche Felder gespeichert werden und wie lange. Art. 5 DSGVO verlangt Datenminimierung und Speicherbegrenzung, und die LDI NRW verlangt eine ergänzte Datenschutzerklärung, wenn es ein Kontaktformular gibt.

#Ist eine Action von außen erreichbar?

Ja. Nach der Dokumentation sind Actions öffentliche Endpunkte unter /_actions/. Darum prüfe ich Eingaben im Schema und Berechtigungen im Handler, und security.checkOrigin bleibt eingeschaltet.

#Kommen Sie für das Projekt nach Wuppertal?

Nein. Ich arbeite von Gdynia aus ausschließlich schriftlich: Briefing, Rückfragen, Umfang, Testumgebung zur Abnahme. Meetings und Telefonate gibt es nicht. Eine erste Einschätzung bekommen Sie schriftlich und ohne Berechnung.

#Schreiben Sie mir

Schicken Sie mir über das Kontaktformular die Adresse Ihrer Website, Ihr Ziel, Ihren Termin und den aktuellen Stack, am besten mit den Formularen, die heute Anfragen erzeugen, und dem Ort, an den diese Anfragen gehen. Ich lese alles, frage schriftlich nach und antworte mit einer ersten Einschätzung zu Umfang und Annahmen. Dafür berechne ich nichts. Passt Astro nicht zu Ihrem Vorhaben, schreibe ich das offen und nenne die bessere Lösung.

Brauchen Sie die Leistung: Astro-Entwickler in Wuppertal?

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

Projekt beschreiben

Weitere WordPress-Dienste und Wissensbasis entdecken