Invisible Docs
GalerieTokens

Rendering-Pipeline

Wie aus Definitionen und einem Stück JSON eine fertige, interaktive Seite wird — in zwei strikt getrennten Zeiten.

Teil 1: Build-Zeit — aus Quelle wird Registry

npm run build läuft in drei Stufen, jede blockiert bei Fehlern (Exit ≠ 0):

  • 1a. Token-Compiler (build/tokens.mjs): prüft die komplette Token-Kette streng und emittiert tokens.css (die eine Laufzeit-Wahrheit), tokens.tailwind.css (@theme-Mapping für den Bausteine-Build) und tokens.json (Modell für PHP).
  • 1b. Registry-Build (build/registry.mjs): scannt definitions/*/, validiert Manifest gegen Schema, ID-Namensraum, Entrypoint-Existenz, Targets, Props-Schemas, Dependencies (zyklenfrei) → registry.cache.php — die Laufzeit liest nie Verzeichnisse.
  • 1c. Asset-Pipeline (build/assets.mjs): CSS wird mit Tailwind kompiliert (jedes @apply vollständig aufgelöst — zur Laufzeit läuft kein Tailwind), Client-Controller mit esbuild gebündelt, Dateinamen content-gehasht. Ein Token-Verwendungs-Check macht Tippfehler in Token-Namen zu Build-Fehlern.

Teil 2: Anfrage-Zeit — aus JSON wird HTML

Laden mit Limits: Größenlimit (256 kB) VOR dem Parsen, JSON mit Tiefenbegrenzung. Der Node-Walker geht rekursiv durch den Baum (max. 500 Nodes, Tiefe 20 — danach Fallback statt Absturz). Pro Node:

  • nodeId/definition validieren → Definition aus der Registry (unbekannt → sichtbarer Fallback-Kasten + Trace-Warnung)
  • Props aufbereiten: nicht deklarierte Props verwerfen (Whitelist), Defaults einsetzen, ungültige Enum-Werte auf Default zurückfallen, responsive Objekte normalisieren, maxLength kappen
  • Slots zuerst: Kinder rekursiv rendern, Ergebnis als fertiges HTML in $ctx['slots']
  • Render-Vertrag ausführen — Escaping passiert IM Renderer; wirft er, gibt es einen Fallback für DIESEN Node, nie einen Fatal für die Seite
render.phpphp
// Der komplette Render-Vertrag einer Definition:
return function (array $props, array $ctx = []): string {
    return '<div class="invisible-card">'
        . ($ctx['slots']['default'] ?? '')
        . '</div>';
};

Die Profil-Hülle: Das Target-Profil baut das Dokument um den gerenderten Baum: tokens.css, dann NUR die Assets der tatsächlich verwendeten Definitionen — invisible_require() sammelt sie während des Walkens, löst die Dependency-Kette auf (FAQ zieht Accordion zieht Icon) und dedupliziert.

Render-Cache: Publizierte Surfaces werden als fertiges HTML abgelegt. Der Cache-Key enthält Surface-ID + Version + Target + Token-Build-Stand + Asset-Stand — ein Token-Update invalidiert automatisch alle betroffenen Seiten. Niemand leert je einen Cache von Hand.

Einbettung in bestehende Systeme

AndockpunktAufrufTypischer Einsatz
Einzelner Bausteininvisible_render_id($id, $props, ['slots' => …])Invisible-Bausteine mitten in einer Bestandsseite — schrittweise Migration
Ganze Surfaceinvisible_render_surface($surface, $options)Host-System erzeugt JSON selbst (Workflows, Agenten, Generatoren)
Publizierte Seiteinvisible_render_published($id)Produktion: Gates garantiert bestanden, Cache aktiv

Jeder Render erzeugt einen Trace (Request-ID, Node-Zahl, Fallbacks, Warnungen, Dauer, Cache-Status). Faustregel: „sauber" heißt null Fallbacks, null Warnungen.