Astro-Entwickler in München

Wie ein Münchner Betrieb auf einer statischen Astro-Seite Login, Konto und personalisierte Teile umsetzt: Sessions-API, Middleware, Server Islands und Cookies nach § 25 TDDDG.

Astro-Entwickler

Migration von WordPress zu Astro in München

Viele Unternehmen in München 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.

#Eine statische Seite mit einem Login: wo die Grenze verläuft

Die meisten Seiten eines Betriebs sind für alle Besucher gleich: Leistungen, Referenzen, Kontakt, Blog. Ein Teil ist es nicht: ein Kundenkonto, ein Händlerbereich, eine Statusabfrage, ein Warenkorb. Auf der Seite der Landeshauptstadt München zu den Online-Services stehen zum Beispiel Statusabfragen für Personalausweis, Reisepass und Führerschein neben Leistungen wie Gewerbe anmelden, ummelden und abmelden. Eine Statusabfrage ist ein gutes Muster für den Unterschied: Der Rahmen der Seite ist für alle gleich, der Inhalt gehört genau einer Person.

Astro trennt das von Haus aus. Laut Dokumentation werden Seiten, Routen und Endpunkte standardmäßig beim Build als statische Seiten erzeugt. Nur was Sie ausdrücklich ausnehmen, wird bei jeder Anfrage berechnet. Dafür braucht das Projekt einen Adapter für die Hosting-Umgebung; die Wahl der Umgebung ist ein eigenes Thema und steht auf der Seite zu Hosting-Adaptern in Berlin. Dieser Text behandelt, was danach kommt: Sessions, geschützte Routen, personalisierte Teile und das Cookie.

Herbstliche Isar an den Isarauen bei München

Foto: Achim Lammerts (Syntaxys), CC BY-SA 4.0, Wikimedia Commons.

#Was statisch bleibt und was nicht

Eine einfache Aufteilung, die ich mit Ihnen vor dem Start schriftlich festhalte:

BereichRenderingGrund
Startseite, Leistungsseiten, Blogbeim Buildgleicher Inhalt für alle, per CDN ausgeliefert
Login-Seite, Konto, Bestellstatusauf AnfrageInhalt hängt von der angemeldeten Person ab
Konto-Menü oder Warenkorb-Zähler in der KopfzeileServer Islanddie Seite bleibt statisch, nur das Fragment ist personalisiert
Formular-Endpunkte, Login-Endpunktauf Anfragenehmen Daten entgegen, siehe Formulare in Wuppertal und Endpunkte in Hannover

Eine Seite mit Rendering auf Anfrage markieren Sie mit export const prerender = false;. Wer fast alles auf Anfrage rendern will, kann output: 'server' setzen und einzelne Seiten mit prerender = true zurückholen. Die Dokumentation sagt dazu, dieser Modus bringe keine zusätzlichen Funktionen, er ändere nur die Vorgabe, und empfiehlt den Start im statischen Modus. Dem folge ich.

#Die Sessions-API und ihre Speichertreiber

Die Sessions-API gibt es seit Astro 5.7.0. Die Daten liegen auf dem Server, im Browser liegt nur ein Cookie mit der Session-ID. Damit passen auch größere Datenmengen hinein, die in einem Cookie nichts verloren hätten, etwa ein Warenkorb.

Der Zugriff sieht in einer Seite so aus:

---
export const prerender = false;
const cart = await Astro.session?.get('cart');
---
<a href="/warenkorb">{cart?.length ?? 0} Artikel</a>

In Endpunkten, Actions und Middleware heißt das Objekt context.session. Für die meisten Fälle genügen get() und set(); regenerate() und destroy() erzeugen eine neue Session-ID beziehungsweise beenden die Session. Beim Login rufe ich regenerate() auf, beim Logout destroy().

Drei Punkte entscheiden über den Betrieb:

  • Speichertreiber. Ohne Treiber gibt es keine Sessions. Die Adapter für Node, Cloudflare und Netlify richten einen Standardtreiber ein. Bei anderen Adaptern tragen Sie einen ein, die Dokumentation zeigt für Vercel einen LRU-Cache, die Konfigurationsreferenz ein Redis-Beispiel über sessionDrivers.redis. Der Treiber wird beim Build festgelegt; soll er zur Laufzeit wechseln, zeigt driver.entrypoint auf eine eigene Datei.
  • Cookie. Voreingestellt sind der Name astro-session, sameSite: lax, httpOnly und secure. Name und Optionen lassen sich unter session.cookie ändern.
  • Lebensdauer. session.ttl ist standardmäßig unbegrenzt, die Werte verfallen also nie von selbst. Ein gesetzter Wert löscht den Eintrag laut Dokumentation erst beim nächsten Zugriff nach Ablauf, nicht automatisch im Speicher. Wer das braucht, nutzt die ttl-Option des Treibers.

Sessions sind in Edge-Middleware nicht unterstützt. Das gehört in die Hosting-Entscheidung, bevor Sie sich festlegen. Werte werden mit devalue serialisiert; erlaubt sind unter anderem Zeichenketten, Zahlen, Datumswerte, Map, Set, Arrays und einfache Objekte, keine Funktionen. Mit session: false lässt sich die Funktion abschalten.

#Middleware für geschützte Routen

Middleware läuft vor jeder Anfrage, kann context.locals füllen und mit next() die Antwort verändern. Wichtig für statische Seiten: Bei vorgerenderten Seiten läuft sie beim Build, nicht beim Besuch. Eine Prüfung im Browserkontext findet dort nie statt. Eine geschützte Seite muss deshalb auf Anfrage gerendert werden, sonst steht ihr Inhalt für alle im ausgelieferten HTML.

Ein Grundgerüst, das ich als Ausgangspunkt nutze:

// src/middleware.ts
import { defineMiddleware } from 'astro:middleware';

export const onRequest = defineMiddleware(async (context, next) => {
  if (context.url.pathname.startsWith('/konto')) {
    const user = await context.session?.get('user');
    if (!user) return context.redirect('/login');
    context.locals.user = user;
  }
  return next();
});

Die Authentifizierungsanleitung von Astro warnt davor, Zugriff nur über den Vergleich von context.url.pathname mit Zeichenketten zu steuern, weil der öffentliche Pfad vom Pfad der passenden Route abweichen kann. Sie empfiehlt eine Prüfung dort, wo Routen zugeordnet werden. Deshalb prüfe ich zusätzlich in jeder geschützten Seite und in jedem Endpunkt selbst, nicht nur in der Middleware. Mehrere Middleware-Funktionen reihe ich mit sequence() auf, zum Beispiel erst Anfrage-Validierung, dann Anmeldung.

Wer keine eigene Anmeldung bauen will, findet in der Anleitung Better Auth, Clerk, Lucia und Scalekit sowie Beschreibungen für Supabase und Firebase. Clerk hängt sich zum Beispiel mit clerkMiddleware() als onRequest ein. Ich wähle eine Lösung nach Datenhaltung und Pflegeaufwand, nicht nach Vorliebe. Wenn Sie einen WordPress-Mitgliederbereich ablösen, stehen Konten, Rollen und Passwort-Hashes auf der Seite Mitgliederbereich migrieren, Nürnberg; das wiederhole ich hier nicht.

#Server Islands für das personalisierte Fragment

Nicht jede Seite mit einem Namen in der Kopfzeile braucht Rendering auf Anfrage. Mit server:defer an einer Komponente wird sie ein eigenes Island: Die Seite liefert Astro statisch aus, die Komponente holt der Browser getrennt nach, jede unabhängig von den anderen.

---
import AccountMenu from '../components/AccountMenu.astro';
---
<AccountMenu server:defer>
  <a slot="fallback" href="/login">Anmelden</a>
</AccountMenu>

Der Inhalt von slot="fallback" steht in der ersten Antwort, bis das Island geladen ist. Ein paar Regeln aus der Dokumentation:

  • Das Island braucht einen Adapter, weil es auf Anfrage gerendert wird.
  • Props müssen serialisierbar sein; Funktionen gehen nicht. Astro verschlüsselt die Props, der Schlüssel entsteht bei jedem Build neu. Bei Rolling Deployments, mehreren Regionen oder CDN-Caching können Front- und Backend verschiedene Schlüssel haben; dann erzeugt astro create-key einen Schlüssel, den Sie als ASTRO_KEY in der Build-Umgebung setzen.
  • Cookies sind im Island lesbar, Astro.url und Astro.request.url zeigen aber auf /_server-islands/..., nicht auf die Seite. Die Seiten-URL liefert der Referer-Header.
  • Die Props reisen als verschlüsselter Query-String in einer GET-Anfrage, normale Cache-Control-Header gelten. Ab 2048 Byte schaltet Astro auf POST um; die kann der Browser nicht cachen.

Für den Cache gilt bei Personalisierung ein eigener Gedanke: Eine Antwort mit dem Namen einer Person darf kein gemeinsamer Cache an andere ausliefern. Ob Ihr CDN die Antwort des Islands zwischenspeichert, prüfe ich im Staging an den echten Antwort-Headern, bevor ich es als erledigt melde. Dasselbe gilt für das Lesen der Session im Island auf Ihrem Adapter. Die Client-Seite, also interaktive Komponenten mit client:-Direktiven, steht auf der Seite Astro-Inseln in Wiesbaden.

#Cookies und § 25 TDDDG

Das Session-Cookie ist ein Eingriff ins Endgerät. § 25 Absatz 1 TDDDG erlaubt das Speichern von Informationen im Endgerät und den Zugriff darauf nur, wenn der Endnutzer auf der Grundlage klarer und umfassender Informationen eingewilligt hat. Absatz 2 Nr. 2 nimmt die Speicherung aus, die unbedingt erforderlich ist, damit der Anbieter einen vom Nutzer ausdrücklich gewünschten digitalen Dienst zur Verfügung stellen kann (Gesetzestext).

Meine technische Lesart, keine Rechtsberatung:

  • Anmeldung, Warenkorb im laufenden Besuch, Sicherheits-Token: Das Cookie trägt etwas, das die Person gerade ausdrücklich nutzt. Das fällt nach meiner Lesart unter Absatz 2 Nr. 2. Die Datenschutzerklärung nennt es trotzdem.
  • “Angemeldet bleiben” über Wochen: Ein sehr langes session.ttl oder maxAge passt nur, wenn die Person das ausdrücklich gewählt hat, etwa mit einem Häkchen. Ein unbegrenzter Standardwert ist dafür der falsche Ausgangspunkt.
  • Personalisierung für Empfehlungen, Reichweitenmessung, Werbung: Das dient nicht dem ausdrücklich gewünschten Dienst und braucht in der Regel eine Einwilligung. Drittanbieter-Skripte nach Einwilligung laden, behandelt die Seite zu Köln; Sicherheits-Header für die Antworten die Seite zu Frankfurt.

Für Betriebe mit Sitz in Bayern ist die Aufsicht das Bayerische Landesamt für Datenschutzaufsicht (BayLDA), das sich unter anderem an bayerische nichtöffentliche Stellen richtet. Hinweise und Kontaktwege stehen auf der Seite des Landesamts. Welche Bewertung für Ihren Fall gilt, klärt Ihre Datenschutzbeauftragte, Ihr Datenschutzbeauftragter oder Ihre Kanzlei; ich liefere die technische Liste der gesetzten Cookies mit Name, Zweck und Lebensdauer.

#Prüfliste für Login auf einer statischen Seite

Auch ohne mich nutzbar:

FrageSoll
Welche Seiten sind personenbezogen?Jede ist mit prerender = false markiert, keine steht im statischen Build
Wo liegt die Session?In einem eingetragenen Treiber, nicht im Arbeitsspeicher einer einzelnen Instanz
Wie lange gilt sie?session.ttl ist bewusst gesetzt, nicht unbegrenzt
Was prüft den Zugriff?Middleware plus Prüfung in Seite und Endpunkt
Wie wird beim Login die ID erneuert?regenerate() beim Login, destroy() beim Logout
Was zeigt ein Island?Nur Daten der angemeldeten Person, Fallback ohne personenbezogene Daten
Was cached das CDN?Personalisierte Antworten sind ausgenommen, geprüft im Staging
Welche Cookies setzt die Seite?Liste mit Name, Zweck, Lebensdauer in der Datenschutzerklärung

#So läuft ein Projekt mit mir

Ich bin ein einzelner Entwickler und arbeite ausschließlich schriftlich und aus der Ferne, ohne Termine und Anrufe. Der Ablauf: Sie schicken mir Ihr Ziel und den Ist-Zustand; ich stelle Rückfragen schriftlich; Sie erhalten einen schriftlichen Umfang mit Annahmen, was statisch bleibt und was auf Anfrage läuft. Ich baue auf einer Staging-Umgebung, Sie nehmen schriftlich ab, danach geht es live. Eine Wartung danach ist optional.

Layout, Grafik und Wireframes liefern Sie; ich setze sie um. Für den Start brauche ich Zugang zum bisherigen System oder dem Quellcode, Ihre Vorgabe, welche Ansichten Ihre Kunden nach der Anmeldung sehen, und die Angabe, wo der Identity-Provider liegt, falls es schon einen gibt.

#Fragen zu Sessions, Login und Datenschutz

#Muss meine ganze Astro-Website auf Serverbetrieb umgestellt werden, nur weil es einen Login gibt?

Nein. Astro rendert Seiten standardmäßig beim Build. Nur die Seiten, die eine Anmeldung oder Personendaten brauchen, bekommen mit export const prerender = false das Rendering auf Anfrage. Leistungsseiten, Blog und Landingpages bleiben statisch. Dafür braucht das Projekt einen Adapter für die gewählte Hosting-Umgebung.

#Wo speichert Astro die Session-Daten?

Auf dem Server, in einem Speichertreiber. Im Browser liegt nur ein Cookie mit der Session-ID, standardmäßig astro-session mit httpOnly, secure und sameSite lax. Die Adapter für Node, Cloudflare und Netlify bringen einen Standardtreiber mit; bei anderen Adaptern wie Vercel tragen Sie einen Treiber selbst ein, etwa Redis oder einen LRU-Cache.

Für ein Cookie, das nur die Anmeldung eines Nutzers trägt, greift nach meiner Lesart § 25 Absatz 2 Nr. 2 TDDDG: unbedingt erforderlich für einen vom Nutzer ausdrücklich gewünschten Dienst. Cookies für Reichweitenmessung oder Werbung fallen nicht darunter. Das ist eine technische Einordnung, keine Rechtsberatung; die endgültige Bewertung liegt bei Ihrer Datenschutzbeauftragten, Ihrem Datenschutzbeauftragten oder Ihrer Kanzlei.

#Was ist ein Server Island und wann lohnt es sich?

Ein Server Island ist eine Komponente mit der Direktive server:defer. Die Seite wird statisch ausgeliefert, die Komponente lädt der Browser danach getrennt vom Server nach. Das lohnt sich für kleine personalisierte Teile wie ein Konto-Menü oder einen Warenkorb-Zähler auf einer sonst gleichen Seite. Für ganze Kontobereiche ist eine Seite mit Rendering auf Anfrage der einfachere Weg.

#Kann ich einen bestehenden Identity-Provider oder eine fertige Login-Lösung anbinden?

Ja. Die Astro-Dokumentation nennt für Authentifizierung unter anderem Better Auth, Clerk, Lucia und Scalekit sowie Anleitungen für Supabase und Firebase. Welche Lösung passt, hängt davon ab, wo Ihre Konten schon liegen und wo die Daten verarbeitet werden dürfen. Das kläre ich schriftlich mit Ihnen, bevor eine Zeile Code entsteht.

#Welche Daten gehören in die Session?

Was die Seite während des Besuchs braucht: die Nutzer-ID, die Rolle, einen Warenkorb. Passwörter und vollständige Kundendatensätze gehören nicht hinein, sie bleiben in der Datenbank oder im Identity-Provider und werden pro Anfrage über die ID geladen. Astro serialisiert Session-Werte mit devalue, Funktionen sind nicht möglich. Den Umzug eines WordPress-Mitgliederbereichs mit Passwort-Hashes behandelt die Seite zur Migration in Nürnberg.

#Schreiben Sie mir Ihre Login-Anforderung

Wenn Ihr Betrieb in München oder Bayern eine Astro-Seite mit Kundenkonto, Händlerbereich oder personalisiertem Teil plant, schreiben Sie mir über das Kontaktformular. Hilfreich sind die Adresse der Website, Ihr Ziel, ein gewünschter Termin, der aktuelle Stand der Technik und eine grobe Zahl der Konten. Die erste schriftliche Einschätzung bekommen Sie kostenlos, mit einem Vorschlag, welche Teile statisch bleiben und welche auf Anfrage laufen.

Brauchen Sie die Leistung: Astro-Entwickler in München?

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

Projekt beschreiben

Weitere WordPress-Dienste und Wissensbasis entdecken