Invisible Docs
GalerieTokens

Die zwei Türen: wie wird es genutzt?

Anwendungen sprechen auf zwei verschiedenen Wegen mit Invisible — beide Türen konsumieren dieselben Definitionen, deshalb sieht alles gleich aus.

Tür 1 — PHP-Bibliothek (Anwendungsseiten)

Für Seiten, deren Aufbau Code bestimmt und deren Inhalt Live-Daten sind: tricoma-Masken, Listen, Detailseiten. Der Datenlieferant ist die Anwendung selbst — SQL, bestehende Funktionen, volle PHP-Freiheit. Kein JSON-Dokument, keine Datenquellen-Schicht, keine Surface nötig:

datachange_kunden.phpphp
// 1. Daten holen (bestehendes PHP)
$rows = kunden_rest_list([...]);

// 2. Props bauen — hier lebt die Fachlogik (Töne, Links, Spalten)
$listProps = [
    'columns' => [
        ['key' => 'name',   'label' => 'Kunde',  'type' => 'link', 'href' => 'kunde.php?id={id}'],
        ['key' => 'status', 'label' => 'Status', 'type' => 'badge'],
    ],
    'rows' => $rows,
];

// 3. Innen rendern: Liste → HTML
$listHtml = invisible_render_id('component.table', $listProps);

// 4. Außen rendern: HTML in die Slots des Skeletts
echo invisible_render_id('template.app.shell', [],
    ['slots' => ['sidebar' => $nav, 'main' => $listHtml]]);

Der Fluss ist immer derselbe: Props gehen in Renderer hinein, HTML kommt heraus und wandert eine Ebene höher in einen Slot. Fachliche Logik (welche Zeile welchen Badge-Ton bekommt) bleibt in der Anwendung — Bausteine kennen nur semantische Vorräte (tone: success|danger), das Theme entscheidet das Aussehen.

Tür 2 — Surface-JSON (redaktionelle Seiten)

Für Seiten, deren Aufbau redaktionell gepflegt wird: Websites, Landingpages, CMS-Inhalte. Die Seite steht als JSON-Dokument (Surface) fest — dieselben Definitionen, aber die Slot-Füllung ist gespeichert statt programmiert:

kunden-landing.jsonjson
{
  "schemaVersion": "1.0",
  "surfaceId": "kunden-landing",
  "targetProfile": "web.document",
  "root": {
    "nodeId": "node-root",
    "definition": "template.page",
    "slots": {
      "header": [{ "nodeId": "node-nav", "definition": "component.navigation",
                   "props": { "brand": "tricoma", "items": ["..."] } }],
      "main":   [{ "nodeId": "node-hero", "definition": "section.hero",
                   "props": { "title": "…" }, "hideOn": ["mobile"] }]
    }
  }
}

Rendern: invisible_render_surface($surface). Nur an dieser Tür gibt es Datenquellen-Bindings ($bind) — weil hier kein Programmierer die Daten heranträgt. Die Werkzeuge zum visuellen Bauen und Publizieren solcher Seiten (Builder, Publish-Workflow) sind das CMS-Produkt auf dem Framework — seit 2026-08-10 in archiv/.

Welche Tür wofür?

AspektTür 1 — PHPTür 2 — Surface-JSON
SeitentypAnwendung (Masken, Listen, Dashboards)redaktionell (Website, Landingpage)
Aufbau bestimmtCode, pro Requestgespeichertes Dokument
Daten kommen vonder Anwendung selbst (SQL, Funktionen)Datenquellen-Bindings ($bind)
Surface nötig?neinja — die Surface IST die Seite

Der Shop ist die Mischung: Aufbau der Produktseite redaktionell (Tür 2), die Produktdaten zur Laufzeit aus der Anwendung.

Bausteine bauen (Entwickler)

Als Ordner unter definitions/<ebene>/<name>/ mit Manifest, Props-Schema, Renderer, CSS und Demo (Checkliste: definitions/README.md). npm run build validiert streng und macht den Baustein überall gleichzeitig verfügbar. Durchsuchen: UI-Kit-Galerie, Tokens: Token-Browser.