Architektur
Renick.Content hat drei Schichten:
- Content. Ein Dokument ist eine Liste typisierter Blöcke, gespeichert als JSON in einem Host-Feld: einem Tailor-Eintrag, einem Model-Attribut, einer RainLab.Pages-Seite oder einem RainLab.Blog-Beitrag. JSON Schema v1 definiert das Format; jeder Schreibvorgang wird validiert.
- Editor. Eine TipTap-3-/React-19-Insel, eingebunden vom Formular-Widget
contenteditor. Das Bundle inassets/distist committet, eine Installation führt also nie eine JS-Toolchain aus. - Rendering.
BlockRendererwandelt das JSON pro Request in HTML um (überrenickContent,content_render()oder|rc_blocks) und wendet Sichtbarkeitsregeln serverseitig an.
Komponentenübersicht
Beim Speichern normalisiert DocumentSaveGuard das Dokument, validiert es strikt und prüft BlockRules. Regelverstöße, die das gespeicherte Dokument schon hatte, blockieren das Speichern nicht. Nach dem Speichern des Hosts werden eine Version erfasst und der Media-Usage-Index aktualisiert.
Das Dokument lebt im Host. Die eigenen Tabellen des Plugins sind Sidecars: renick_content_versions (Snapshots, Audit-Log), renick_content_templates, renick_content_media_usage, renick_content_shared (Geteilte Inhalte), renick_content_scripts (Custom Scripts), renick_content_api_tokens (gehasht) und renick_content_ai_usage (monatliches KI-Budget).
Aufbau des Plugins
plugins/renick/content/
├── Plugin.php # registrations only
├── routes.php # REST API (off by default), tile/thumb proxies, form endpoints
├── blocks/ # <handle>/<handle>.yaml definition + <handle>.htm partial
├── classes/ # renderer, document model, Content/ContentApi facades, Integrations/, TailorList/, ai/
├── components/ # renickContent, Entry List, submission form
├── contentfields/ # Tailor content field
├── controllers/ # backend pages (tokens, audit log, scripts, shared content, templates)
├── formwidgets/ # ContentEditor, icon picker
├── console/ # renick:content:* commands
├── models/
├── schema/document-v1.json
├── assets/ # src/ editor source; dist/ and frontend/ committed bundles
└── tests/ # PHPUnit; Playwright e2e lives in /tests-e2eEinstieg: Das Feld einbinden, Blöcke erstellen, die PHP API oder die REST API.