Erscheinungsbild
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:
- Schema und Kombinationsregeln (
src/lib/config/schema.ts) — ohne Seiteneffekte, deshalb isoliert testbar. Hier liegen auch die verbotenen Kombinationen. - Umgebungsabhängige Prüfungen (
src/lib/config/environment.ts), ausgeführt von einer Astro-Integration im Hookastro: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.defaultOgImagegegen das Asset-Manifest fehlt noch; das Manifest entsteht in M3.