Skip to content

feat(surface): Block-Bundles laden, auch wo keine Fläche ist - #189

Merged
BechsteinDigital merged 3 commits into
mainfrom
feat/composer-block-bundles
Aug 7, 2026
Merged

feat(surface): Block-Bundles laden, auch wo keine Fläche ist#189
BechsteinDigital merged 3 commits into
mainfrom
feat/composer-block-bundles

Conversation

@BechsteinDigital

Copy link
Copy Markdown
Owner

1. Why is this change necessary?

Der Canvas rendert die echten Block-Komponenten. Die gibt es nur, wenn ihre Plugin-Bundles
geladen sind — und im Admin lädt die Shell ausschließlich Bundles der admin-Fläche. Bis hierher
war die Block-Registry im Editor leer, und der Canvas hätte nur Platzhalter zeigen können.

§7.4 benennt den Befund selbst: Die Fähigkeit gehört nach @callora/surface, parametrisiert nach
Ziel-Surface, nicht in den Composer. Der Composer könnte sie sich bauen — das wären keine
Sonderrechte, sondern gewöhnliche Plugin-Arbeit. Aber jeder Editor täte es dann erneut, und die
Fehlertoleranz samt Ladetelemetrie gäbe es doppelt.

2. What does this change do, exactly?

loadSurfaceBundles ist eine Funktion und nicht zwei, und das ist der Kern. Ein Bundle, das
vor der Registry läuft, registriert ins Leere: registerBlock warnt in die Konsole und kehrt
zurück, weil ein Plugin die Shell nie brechen darf. Übrig bliebe ein leerer Canvas — kein Fehler,
nichts zu finden. Ein Vertrag soll solche Fehler unerreichbar machen, nicht dokumentieren.

ensureSurfaceRegistry ersetzt nie. Ein zweiter Aufruf, der austauschte, verlöre jeden
registrierten Block — und der Loader überspringt ein Skript, das schon im Dokument steht, könnte
sie also nie wieder füllen. Die Blöcke wären dauerhaft weg, still.

injectStyles: false ist kein Detail. Ein Flächen-Stylesheet beansprucht Namen wie
.cal-header, die auf beiden Seiten etwas bedeuten. Eingebunden gestaltete es die Admin-Shell
um den Canvas herum um — genau das Entkommen, gegen das #187 das Scoping gebaut hat. Die URLs
kommen so oder so zurück; der Editor holt den Text und scoped ihn.

Der Entwurf sagt jetzt, wohin er gehört. workspaceKey und surfaceKey stehen in der
Antwort, weil ein Layout für den Kiosk nicht aus den Blöcken der Standardfläche gebaut werden
darf. Ein ungebundenes Layout behält null statt "default" — eingesetzt sähe es auf der Leitung
aus wie ein Layout, das wirklich an die Standardfläche gebunden ist, und der Editor bäute
stumm gegen die falschen Blöcke. Stattdessen sagt die Seite es hin.

Damit ist auch §7.6 Bedingung 2/3 wirklich verdrahtet: Theme-Tokens und Sektions-CSS kommen jetzt
von den echten Endpunkten in den Canvas, statt dass die Fähigkeit ungenutzt dasteht.

3. Describe each step to reproduce the issue or behaviour.

Alle fünf Aussagen der Editor-Seite gegengeprüft — jede sabotiert, jede beißt. Ebenso die vier des
Ladevertrags (Registry-vor-Skript, keine Ersetzung, Ziel-Surface durchgereicht, Styles nicht
eingebunden).

Gate Ergebnis
.NET 1982 + 29 Analyzer
Surface Runtime 109
Composer Admin 21
Admin Shell 521
Docs Site lint + build

4. Please link to the relevant issues (if any).

Setzt den in §7.4 benannten Plattform-Befund um. Baut auf #186 (Admin-API) und #187 (Canvas) auf.


Zwei Dinge, die nicht im Auftrag standen

Die Surface-Anleitung war falsch. Sie nannte durchgehend @callora/surface-sdk unter
custom/surface-sdk/ — ein Paket, das mit der SDK-Productization verschwunden ist. Wer ihr folgte,
kam bis npm install und dann nicht weiter. Zwei sachliche Fehler steckten mit drin: Das
Default-Surface-Segment stand als workspace statt surface (das Bundle landete unter
public/workspace und würde vom Loader nie geholt — kein Fehler, nur eine leere Fläche), und eine
View bekommt zwei Props, nicht eines (params war gar nicht erwähnt).

Das Doku-Gate war rot, ohne dass jemand ein Dokument geändert hatte. markdownlint-cli2 steht
auf ^0.23.2, eine Minor brachte MD060 mit, und die Regel schlug auf 148 Zeilen in 11 unberührten
Dateien an. Die Konfiguration hat dafür schon eine Antwort im Kopfkommentar — „structure-strict,
style-permissive: catch broken markdown, not stylistic taste"
—, und genau darum sind MD004,
MD046 und MD049 bereits aus. Dazu drei cspell-Treffer, die ich selbst mit den Data-Contributors
hereingetragen hatte.

Noch nicht drin

  • Drag & Drop und das generierte Konfigurationspanel.
  • Der Klick-Konflikt (§7.6): ein Edit-Layer mit „Interaktiv testen"-Umschalter.
  • Die Block-Palette — und damit die Frage, wie das Angebot gefiltert wird, wenn der Editor
    zwischen Flächen wechselt. Die Registry sammelt Blöcke additiv (richtig, sonst gingen sie
    verloren); das Filtern gehört an die Palette, nicht an die Registry.

BechsteinDigital and others added 3 commits August 7, 2026 11:43
Der Canvas rendert die echten Block-Komponenten. Die gibt es nur, wenn ihre
Plugin-Bundles geladen sind — und im Admin lädt die Shell ausschließlich Bundles
der `admin`-Fläche. Ohne diesen Schritt bliebe die Block-Registry leer.

Die Fähigkeit gehört nach @callora/surface, nicht in den Composer (§7.4): Der
Composer könnte sie sich bauen, aber jeder Editor täte es dann erneut, und die
Fehlertoleranz samt Ladetelemetrie gäbe es doppelt.

`loadSurfaceBundles` ist eine Funktion und nicht zwei, weil die Reihenfolge der
Punkt ist: Ein Bundle, das vor der Registry läuft, registriert ins Leere —
`registerBlock` warnt in die Konsole und kehrt zurück, weil ein Plugin die Shell
nie brechen darf. Übrig bliebe ein leerer Canvas ohne Fehler. Ein Vertrag soll
solche Fehler unerreichbar machen, nicht dokumentieren.

`ensureSurfaceRegistry` ersetzt nie. Ein zweiter Aufruf, der die Registry
austauschte, verlöre jeden registrierten Block — und der Loader überspringt ein
Skript, das schon im Dokument steht, könnte sie also nie wieder füllen. Die
Blöcke wären dauerhaft weg, still.

`injectStyles: false` ist kein Detail. Ein Flächen-Stylesheet beansprucht Namen
wie `.cal-header`, die auf beiden Seiten etwas bedeuten; eingebunden gestaltete
es die Admin-Shell UM den Canvas herum um — genau das Entkommen, gegen das das
Scoping gebaut wurde. Die URLs kommen so oder so zurück, der Editor holt den
Text und scoped ihn.

Der Entwurf sagt jetzt, wohin er gehört: workspaceKey und surfaceKey stehen in
der Antwort. Ein ungebundenes Layout behält null statt „default" — eingesetzt
sähe es auf der Leitung aus wie ein Layout, das WIRKLICH an die Standardfläche
gebunden ist, und der Editor bäute stumm gegen die falschen Blöcke.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QvepSeijoZeRaBsyiGqoka
Die Surface-Anleitung nannte durchgehend `@callora/surface-sdk` unter
`custom/surface-sdk/` — ein Paket, das mit der SDK-Productization verschwunden
ist. Wer ihr folgte, kam bis `npm install` und dann nicht weiter. Die Doku ist
die erste Fläche, die ein Plugin-Autor berührt; sie darf nicht auf ein gelöschtes
Verzeichnis zeigen.

Zwei sachliche Fehler steckten mit drin, beide von der Sorte, die eine Stunde
kostet:

- Das Default-Surface-Segment stand als `workspace`, das Preset sagt `surface`.
  Das Bundle landete unter `public/workspace`, käme so ins Manifest und würde
  vom Loader — der auf `surface` filtert — nie geholt. Kein Fehler, nur eine
  leere Fläche.
- Eine View bekommt zwei Props, nicht eines: `params` trägt, was das SSR-Template
  an der Aufrufstelle übergab, und war gar nicht erwähnt.

Dazu, was seither dazugekommen ist: `registerBlock` (eine View plus die
Metadaten, die ein Editor braucht — kein zweites Ding, dieselbe Identität),
`surfaceKeys` an der View, und `loadSurfaceBundles` für Hosts, die
Flächen-Blöcke zeigen, ohne eine Fläche zu sein.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QvepSeijoZeRaBsyiGqoka
Der Doku-Job war rot, ohne dass jemand ein Dokument geändert hatte:
`markdownlint-cli2` steht auf `^0.23.2`, eine Minor brachte MD060
(table-column-style) mit, und die Regel schlug auf 148 Zeilen in 11 unberührten
Dateien an.

Die Konfiguration hat dafür bereits eine Antwort im Kopfkommentar —
„structure-strict, style-permissive: catch broken markdown, not stylistic taste".
Genau darum sind MD004, MD046 und MD049 schon aus. Der Abstand um einen
Tabellen-Pipe ist dieselbe Kategorie.

Ein Gate, das rot wird, ohne dass jemand etwas getan hat, bringt allen bei, es zu
übersehen — und dann sieht auch niemand mehr das Rot, das zählt.

Der zweite Teil desselben Rots — drei cspell-Treffer, deutsche Beispielpfade in
einer englischen Doku, von mir mit den Data-Contributors hereingetragen — steckt
im vorigen Commit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QvepSeijoZeRaBsyiGqoka
@BechsteinDigital
BechsteinDigital merged commit 29d0674 into main Aug 7, 2026
8 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant