Skip to content

0001 — Zentrale Projektkonfiguration mit Validierung zur Bauzeit

Status: angenommen · Milestone: M2

Kontext

Im Referenzprojekt niels-nuebel.de waren projektspezifische Werte über die Codebasis verstreut und fest verdrahtet: GTM-Container-ID im Layout, Domain im Cookie-Reset, Server-Pfade im Workflow. Ein zweites Projekt daraus abzuleiten hätte bedeutet, an Dutzenden Stellen zu suchen und zu ersetzen — fehleranfällig und nicht überprüfbar.

Entscheidung

Es gibt genau eine typisierte Projektkonfiguration, project.config.ts, die über defineProject() beim Import mit Zod validiert wird. astro.config.ts leitet die gesamte Astro-Konfiguration daraus ab und enthält keine eigenen Werte.

Die Validierung ist zweistufig:

  1. Schema und Kombinationsregeln (src/lib/config/schema.ts) — ohne Seiteneffekte, deshalb isoliert testbar. Hier liegen auch die verbotenen Kombinationen.
  2. Umgebungsabhängige Prüfungen (src/lib/config/environment.ts), ausgeführt von einer Astro-Integration im Hook astro:config:setup. Sie brauchen Kontext, den es erst zur Bauzeit gibt: Umgebungsvariablen und installierte Pakete.

Ungültige Konfigurationen brechen den Build ab. Umgebungsabhängige Regeln greifen nur in production, damit ein noch nicht initialisiertes Projekt lokal baubar bleibt.

Begründung

Feature-Flags ohne Validierung erzeugen stille Fehlkonfigurationen: Tracking ohne Consent-Schicht, ein PHP-Formular auf GitHub Pages, Google Ads ohne Marketing-Kategorie. Solche Zustände fallen sonst erst im Produktivbetrieb auf — im schlechtesten Fall als Datenschutzproblem. Ein abgebrochener Build ist die billigste Stelle, das zu bemerken.

Die Trennung in zwei Stufen hält das Schema frei von Seiteneffekten. Dadurch lässt sich jede Regel als schneller Unit-Test prüfen, statt einen vollständigen Build zu starten.

Verworfene Alternativen

Alles in .env. Untypisiert, nicht strukturierbar, keine Kombinationsregeln möglich. Environment-Variablen bleiben deshalb auf das beschränkt, was sich je Umgebung ändert.

JSON oder YAML als Konfigurationsformat. Keine Typen in der Bearbeitung, keine abgeleiteten Werte, keine Kommentare mit Begründungen an Ort und Stelle.

Validierung nur in der Integration. Hätte bedeutet, dass Unit-Tests und andere Werkzeuge mit unvalidierten Objekten arbeiten. defineProject() als einziger Einstieg garantiert dagegen, dass eine ungültige Konfiguration nie im Speicher existiert.

Konsequenzen

  • Jede neue Option braucht einen Schema-Eintrag und, sofern sie mit anderen Optionen interagiert, eine Kombinationsregel samt Test.
  • starter:init (M9) schreibt diese Datei und kann sich auf die Validierung verlassen.
  • Die Prüfung von seo.defaultOgImage gegen das Asset-Manifest fehlt noch; das Manifest entsteht in M3.