Interne Content-API

Zweck

Die Interne Content-API ist eine sichere CMS-API für vertrauenswürdige KI- und Operator-Tools. Sie ermöglicht es diesen Tools, CMS-Content-Verträge einzusehen, Inhalte nach dem Entwurf-zuerst-Prinzip zu erstellen, bestimmte seiteneigene Slots auf bestehenden Entwurfsseiten zu ersetzen und explizite Veröffentlichungsvorgänge über strukturiertes JSON auszuführen, ohne sich in die Browser-Admin-Oberfläche einzuloggen, sie zu scrapen oder zu automatisieren.

Phase 1 ist als tokengeschützte, ausschließlich JSON liefernde, nicht öffentliche API für schreibgeschützte Content-Erkundung sowie die Erstellung von Entwurfsseiten über validierte Content-Pläne implementiert. Phase 2A fügt sichere Grundlagen für Navigationsmenüs, Shared Slots und die explizite Zuweisung von Shared Slots zu Seiten-Slots hinzu. Phase 2B fügt kontrolliertes, auf Entwürfe beschränktes Ersetzen von seiteneigenem Slot-Inhalt auf bestehenden Seiten hinzu. Veröffentlichungs-Endpunkte sind explizit und erfordern content.publish; Content-Apply bleibt Entwurf-zuerst und veröffentlicht nicht. Die API bleibt bewusst schmal: kein Remote-Fetch, kein breites Löschen von Seiten über Content-Apply, kein Ersetzen von Slots mit Shared-Slot-Anbindung und kein kaskadierendes Veröffentlichen von Shared Slots.

Produktpositionierung

Die Interne Content-API ist:

  • eine interne/Operator-CMS-API
  • tokengeschützt
  • nicht öffentlich
  • keine Headless-CMS-Auslieferungs-API
  • kein Ersatz für Admin-Berechtigungen
  • kein Ersatz für Import/Export
  • keine Integration eines KI-Anbieters

Der CMS-Kern sollte Eigentümer dieser API sein, weil sie auf zentralen Content-Konzepten arbeitet: Sites, Seiten, Layouts, Slots, Blöcke, Übersetzungen, Navigation und Shared Slots. KI- oder Operator-Tools dürfen die API aufrufen, aber der CMS-Kern sollte keine OpenAI-, LLM-, Crawler- oder anbieterspezifische Integrationslogik einbetten.

Routen-Präfix

Das kanonische Präfix lautet:

/webadmin/api

Damit bleibt die API innerhalb der CMS-Admin-Grenze und nutzt zugleich ein knappes, vertrautes API-Segment. Ressourcenartige Endpunkte sollten direkt unter diesem Präfix liegen, etwa /webadmin/api/pages und /webadmin/api/blocks.

Die API-Erkundung beginnt bei:

GET /webadmin/api

Nicht authentifizierte Aufrufer erhalten nur öffentlich unbedenkliches Bootstrap-JSON. Authentifizierte Aufrufer erhalten sichere Produktversions-Metadaten sowie Links zu OpenAPI, dem KI-Leitfaden, dem Content-Vertrag, Beispielen, Content-Validate/-Apply, Seiten, Navigation und Shared Slots. Externe KI-/Operator-Tools sollten von dieser Live-Erkundungsantwort ausgehen, statt das CMS-Repository oder lokale Paketdokumentation zu lesen.

Planbasierte Content-Operationen verwenden:

POST /webadmin/api/content/validate
POST /webadmin/api/content/apply

Zu vermeidende Routenentscheidungen:

  • /webadmin/internal-api, weil es unnötig lang ist
  • /webadmin/api/content-plans/..., weil content-plans für den URL-Vertrag zu technisch und zu eng ist
  • jede Ressource unter /webadmin/api/content/... zu platzieren, weil Ressourcen-APIs klar und direkt bleiben sollten
  • /admin, weil das CMS nicht annehmen darf, dass der /admin-Pfad des Host-Produkts dem CMS gehört
  • /cms, weil /cms ausschließlich für statische CMS-Assets reserviert bleibt

Authentifizierung

Die API verwendet Bearer-Token-Authentifizierung:

Authorization: Bearer <token>

CMS-API-Tokens werden von einem CMS-Superadmin unter System -> API Tokens erstellt. Das CMS speichert in der Datenbanktabelle cms_api_tokens nur einen SHA-256-Hash sowie eine sichere Vorschau. Das Klartext-Token wird unmittelbar nach der Erstellung einmalig angezeigt und danach nie wieder.

Superadmins können ein Token widerrufen, um den API-Zugriff sofort zu deaktivieren und dabei die Audit-Zeile sichtbar zu halten, oder ein Token löschen, um den Token-Datensatz dauerhaft aus der Liste zu entfernen. Das Löschen eines aktiven Tokens deaktiviert den API-Zugriff ebenfalls sofort, weil der Authentifikator keinen passenden gespeicherten Hash mehr findet.

Lokale KI- und Operator-Tools sollten das erzeugte Token in einem vertrauenswürdigen Operator-Secret-Store ablegen.

Verwenden Sie die Basis-URL der Internen Content-API in der lokalen Operator-Konfiguration:

WEBBLOCKS_CMS_API_URL=https://example.com/webadmin/api
WEBBLOCKS_CMS_API_TOKEN=...

Die CMS-Laufzeit benötigt WEBBLOCKS_CMS_INTERNAL_API_TOKEN nicht.

Authentifizierungsregeln:

  • fehlende, falsche oder widerrufene Tokens liefern JSON 401
  • widerrufene Tokens funktionieren sofort nicht mehr
  • Tokens dürfen niemals in Logs, Diagnosen, Support-Berichten, Tests oder Dokumentationsbeispielen ausgegeben werden
  • der Token-Vergleich muss einen zeitkonstanten Vergleich verwenden
  • erfolgreiche API-Anfragen aktualisieren last_used_at und last_used_ip des Tokens
  • erfolgreiche API-Anfragen speichern zudem einen gekürzten User-Agent für den Operator-Audit-Kontext
  • Antworten sind ausschließlich JSON

Beispielanfrage:

GET /webadmin/api/sites
Authorization: Bearer <token>
Accept: application/json
Content-Type: application/json

Capabilities

Superadmins wählen die Token-Capabilities beim Erstellen eines Tokens unter System -> API Tokens und können Name und Capabilities eines Tokens später bearbeiten, ohne das Token-Secret offenzulegen oder zu rotieren. Die Erkundung zeigt die gespeicherten Capabilities an, ohne den Token-Wert, den Token-Hash oder die Token-Vorschau zurückzugeben. Standard-Tokens für den Seitenaufbau erhalten standardmäßig diese Capabilities:

  • content.read
  • content.validate
  • content.apply
  • navigation.write
  • shared-slots.write

Destruktive und Veröffentlichungs-Capabilities sind separate erweiterte Optionen und standardmäßig nicht ausgewählt:

  • content.publish
  • pages.delete

Schreib-Endpunkte prüfen die jeweilige Capability serverseitig. Fehlende Capabilities liefern JSON 403 mit Hinweisen über api_discovery_url, openapi_url, documentation_url und example_url. Normale Tokens für den Seitenaufbau sollten keine destruktiven Capabilities enthalten.

API-Modell

Die API hat zwei sich ergänzende Modi.

Ressourcen-API

Ressourcen-Endpunkte spiegeln einzelne admin-äquivalente Operationen wider:

  • Seiten auflisten und lesen
  • Blöcke auflisten und lesen
  • Sites, Sprachen (Locales), Layouts und Blocktypen auflisten
  • später Entwurfsseiten-Ressourcen direkt erstellen oder aktualisieren
  • später Seiten-Slots auflisten oder sicherstellen
  • später Blöcke über Ressourcen-Endpunkte hinzufügen, aktualisieren, verschieben und löschen
  • später Kind-Blöcke über Ressourcen-Endpunkte hinzufügen
  • später Navigation und Shared Slots verwalten

Ressourcen-Endpunkte in Phase 1:

GET /webadmin/api/sites
GET /webadmin/api/locales
GET /webadmin/api/page-layouts
GET /webadmin/api/block-types
GET /webadmin/api/content-contract
GET /webadmin/api/pages
GET /webadmin/api/pages/{page}
POST /webadmin/api/pages/{page}/publish
POST /webadmin/api/pages/{page}/publish-page-owned-blocks
POST /webadmin/api/pages/{page}/slots/{slot}/shared-slot
GET /webadmin/api/blocks
GET /webadmin/api/blocks/{block}
GET /webadmin/api/navigation-menus
GET /webadmin/api/navigation-menus/{navigationMenu}
POST /webadmin/api/navigation-menus
POST /webadmin/api/navigation-menus/{navigationMenu}/items
GET /webadmin/api/shared-slots
GET /webadmin/api/shared-slots/{sharedSlot}
POST /webadmin/api/shared-slots
POST /webadmin/api/shared-slots/{sharedSlot}/blocks

Content-Validate-/-Apply-API

Content-Validate-/-Apply-Endpunkte verarbeiten vollständige, mehrstufige Content-Pläne:

POST /webadmin/api/content/validate
POST /webadmin/api/content/apply

validate prüft einen vollständigen Content-Plan und schreibt nichts. apply validiert den Plan erneut und erstellt anschließend die angeforderte Entwurfsseite, Navigationselemente, Shared Slots, Shared-Slot-Blockbäume und Shared-Slot-Zuweisungen für Seiten-Slots in einer Transaktion. Es kann außerdem benannte seiteneigene Slots auf einer bestehenden Entwurfsseite ersetzen, wenn der Plan mode: replace_existing_draft_page verwendet und eine optimistische Sicherheitsprüfung enthält. Das ist nützlich für KI-generierte Seiten, Vorlagen, Starterseiten, gemeinsame Header/Footer und Migrationshelfer, bei denen das CMS halb erstellte Inhalte vermeiden soll.

Der Request-Body darf weiterhin ein Feld plan oder eine andere strukturierte Content-Plan-Payload enthalten. Die URL sollte /content/validate und /content/apply bleiben.

Beide Modi werden benötigt:

  • die Ressourcen-API stellt internen Tools das bestehende CMS-Content-Modell samt Verträgen bereit
  • die Content-Validate-/-Apply-API vermeidet partielle Schreibvorgänge bei größeren Seitenaufbauten

Slot-Ersetzung auf bestehenden Entwurfsseiten

Das Ersetzen auf bestehenden Entwurfsseiten bleibt innerhalb des Validate-/Apply-Vertrags:

POST /webadmin/api/content/validate
POST /webadmin/api/content/apply

Verwenden Sie mode: replace_existing_draft_page, um einen oder mehrere seiteneigene Slots auf einer bestehenden Entwurfsseite zu ersetzen. Die Operation erfordert content.validate für Validate und content.apply für Apply. Sie erfordert kein pages.delete, weil sie keine allgemeine Seitenlöschoperation ist.

Der path der Seitenübersetzung ist die kanonische öffentliche URL. Neue Pläne sollten Pfade wie /contact, /features oder /docs/internal-content-api verwenden; /p/... dient nur der Alt-Kompatibilität. Pfade mit Schrägstrichen werden segmentweise normalisiert, sodass aus /docs/internal-content-api/ der Pfad /docs/internal-content-api wird und er nicht zu docsinternal-content-api zusammengezogen wird. Reservierte Routenbereiche wie /webadmin, /webadmin/api, /cms, /search, /search.json, /contact-messages, /install sowie Host-Auth-Routen können nicht als öffentliche Seitenpfade angelegt werden.

Beispiel:

{
  "plan": {
    "mode": "replace_existing_draft_page",
    "site": "default",
    "locale": "en",
    "page": {
      "id": 9,
      "expected_path": "/contact",
      "status": "draft"
    },
    "replace_slots": {
      "main": [
        {
          "type": "plain_text",
          "translations": {
            "content": "Updated draft contact content."
          }
        }
      ]
    }
  }
}

Regeln:

  • die Zielseite muss den Status draft haben
  • expected_path oder expected_updated_at ist erforderlich
  • expected_path verwendet den kanonischen öffentlichen Seitenübersetzungspfad, keinen /p/...-Alt-Alias
  • die Zielseite muss zur angeforderten Site gehören, und die Sprache (Locale) muss für diese Site aktiviert sein
  • jeder Slot muss auf der Seite existieren und seiteneigene Blöcke verwenden
  • Slots mit Shared-Slot-Anbindung werden abgelehnt statt geleert
  • nur Blöcke in den benannten replace_slots werden entfernt
  • alte Blöcke werden entfernt und neue Blöcke in einer Transaktion geschrieben
  • Seitenrevisionen werden vor und nach dem Apply festgehalten
  • es findet kein Veröffentlichen, kein Medienabruf/-import, kein breites Löschen und kein Leeren von Shared-Slot-Zuweisungen statt

Source-Sync-Metadaten

Content-Pläne dürfen ein begrenztes, geheimnisfreies source_sync-Objekt für KI-/Operator-Doku-Sync-Workflows persistieren. Beliebige Seiteneinstellungen werden abgelehnt. Die akzeptierte Form ist:

{
  "page": {
    "settings": {
      "source_sync": {
        "type": "markdown_documentation",
        "source_id": "webblocks-cms:docs/internal-content-api.md",
        "source_path": "docs/internal-content-api.md",
        "source_sha256": "64-character-lowercase-sha256",
        "managed_slots": ["main"],
        "last_synced_at": "2026-06-25T00:00:00Z"
      }
    }
  }
}

Apply persistiert diese Metadaten in den Seiteneinstellungen, und die API-Antworten für Seitenliste und -detail geben dieselben freigegebenen source_sync-Felder für die spätere Zuordnung zurück. Fügen Sie keine Tokens, Umgebungswerte, absoluten lokalen/Server-Pfade oder anderen Geheimnisse ein.

Explizite Veröffentlichungs-Endpunkte

Das Veröffentlichen ist von Content-Apply getrennt und erfordert ein Token mit content.publish.

POST /webadmin/api/pages/{page}/publish
POST /webadmin/api/pages/{page}/publish-page-owned-blocks

POST /webadmin/api/pages/{page}/publish veröffentlicht den Seitendatensatz. Die Standard-Payload betrifft nur die Seite:

{
  "include_page_owned_blocks": false
}

Regeln:

  • ein weggelassenes include_page_owned_blocks verhält sich wie false
  • include_page_owned_blocks: false veröffentlicht nur den Seitendatensatz und lässt Blöcke im Entwurf oder in Prüfung unverändert
  • include_page_owned_blocks: true veröffentlicht Entwurfs- und In-Prüfung-Blöcke, die den nicht geteilten Seiten-Slots der Seite gehören, einschließlich verschachtelter Kind-Blöcke
  • bereits veröffentlichte Blöcke bleiben unverändert
  • Slots mit Shared-Slot-Anbindung werden ausgeschlossen und in der Antwort gemeldet
  • nicht unterstützte Shared-Slot-Kaskadenfelder wie publish_shared_slots, include_shared_slot_blocks oder shared_slot_cascade liefern JSON 422
  • die Antwort enthält Seiten-ID/Status/Pfad-Metadaten, ob seiteneigene Blöcke einbezogen wurden, die Anzahl der veröffentlichten Blöcke, Zusammenfassungen ausgeschlossener Shared Slots und die Seitenrevisions-ID

POST /webadmin/api/pages/{page}/publish-page-owned-blocks veröffentlicht nur unveröffentlichte seiteneigene Blöcke und ändert den Workflow-Status der Seite nicht. Er verwendet dieselbe Capability content.publish und dieselbe Shared-Slot-Ausschlussregel.

KI-/Operator-Tools dürfen nicht annehmen, dass das Veröffentlichen einer Seite alle Blockinhalte öffentlich macht. Verwenden Sie include_page_owned_blocks: true nur, wenn der Benutzer das Veröffentlichen aller unveröffentlichten seiteneigenen Blöcke dieser Seite ausdrücklich genehmigt hat. Shared-Slot-Inhalte müssen separat geprüft und veröffentlicht werden.

Content-Contract-Endpunkt

GET /webadmin/api/content-contract ist ein schreibgeschützter Erkundungs-Endpunkt für vertrauenswürdige KI-/Operator-Tools. Er liefert das API-Präfix, Validate-/Apply-URLs, die Admin-Vorschau-URL-Vorlage, Sicherheits-Flags, Erkundungs-URLs, empfohlene Seitenaufbau-Muster und bereinigte Block-Vertrags-Metadaten.

Der Endpunkt ist generisches CMS-Produktverhalten. Er darf keine installationsspezifischen Geheimnisse, Token-Werte, rohen Blade-Inhalte, absoluten Dateisystempfade, privaten Serverpfade oder site-spezifischen Anweisungen zurückgeben. Block-Vertragszeilen dürfen Handle/Slug, Label, Kategorie, Status, Container- und Kind-Unterstützung, übersetzbare Felder, gemeinsame Einstellungsfelder und das Root-Verhalten des öffentlichen Renderers enthalten.

KI-Tools sollten diesen Endpunkt oder GET /webadmin/api/block-types aufrufen, bevor sie einen Plan erstellen, und dürfen nur Handles verwenden, die in der aktuellen Installation vorhanden sind.

Der contact_form-Vertrag enthält zusätzliche sichere Formular-Metadaten: Einstellungsschema, übersetzte Felder, den öffentlichen Submit-Endpunkt POST /contact-messages, das erforderliche CSRF-Browser-Verhalten, Server-Validierungsregeln, das CMS-eigene versteckte generierte Anti-Spam-Prüffeld, generisches Erfolgsverhalten des Prüffelds, Hinweise zu Spam-Klassifizierung/Quarantäne, das Speichern-vor-Benachrichtigung-Verhalten, die Empfänger-Fallback-Reihenfolge, die sichere Aufzeichnung von Benachrichtigungsfehlern und das Prüfverhalten unter /webadmin/contact-messages. Das Prüffeld wird vom Renderer generiert, ist nicht Teil der normalen Besuchereingabe und sollte nicht manuell von API- oder KI-/Operator-Tools erstellt werden. Kontaktseiten-Tools sollten diesen nativen Block statt Trusted HTML, rohem Formular-Markup oder mailto:-Formularen verwenden. Das alte Feld website ist nicht mehr Teil des öffentlichen Kontaktformular-Vertrags.

Der menschenlesbare KI-Seitenaufbau-Leitfaden liegt in paketnativen Installationen unter vendor/fklavyenet/webblocks-cms/docs/ai-page-building-guide.md.

Umfang von Phase 1

Erkundungs-Endpunkte

  • GET /webadmin/api
  • GET /webadmin/api/openapi.json
  • GET /webadmin/api/ai-guide
  • GET /webadmin/api/examples
  • GET /webadmin/api/examples/contact-page
  • GET /webadmin/api/examples/landing-page
  • GET /webadmin/api/sites
  • GET /webadmin/api/locales
  • GET /webadmin/api/page-layouts
  • GET /webadmin/api/block-types
  • GET /webadmin/api/content-contract

Seiten-Endpunkte

  • GET /webadmin/api/pages
  • GET /webadmin/api/pages/{page}
  • POST /webadmin/api/pages/{page}/slots/{slot}/shared-slot

Block-Endpunkte

  • GET /webadmin/api/blocks
  • GET /webadmin/api/blocks/{block}

Navigations-Endpunkte

  • GET /webadmin/api/navigation-menus
  • GET /webadmin/api/navigation-menus/{navigationMenu}
  • POST /webadmin/api/navigation-menus
  • POST /webadmin/api/navigation-menus/{navigationMenu}/items

Navigationsmenüs verwenden das bestehende CMS-Modell navigation_items.menu_key. Phase 2A unterstützt die mitgelieferten CMS-Menü-Handles wie primary, footer, mobile, legal und docs; sie fügt keine separate Menütabelle hinzu. Das Erstellen eines Navigationsmenüs wird als Anlegen einer sicheren, site-bezogenen Menügruppe mit optionalen Anfangselementen behandelt. Es verweigert das Überschreiben einer Site/eines Menüs, das bereits Elemente enthält.

Navigationselement-URLs dürfen interne Pfade wie /, /about und /contact oder sichere http-/https-URLs sein. Die API lehnt javascript:, data:, protokollrelative URLs, Pfad-Traversal, fehlerhafte URLs, nicht unterstützte Targets und leere Labels ab. Navigations-Endpunkte erstellen keine Seiten, veröffentlichen keine Seiten, crawlen keine Sites und rufen keine Remote-URLs ab.

Shared-Slot-Endpunkte

  • GET /webadmin/api/shared-slots
  • GET /webadmin/api/shared-slots/{sharedSlot}
  • POST /webadmin/api/shared-slots
  • POST /webadmin/api/shared-slots/{sharedSlot}/blocks

Die Shared-Slot-Erstellung ist site-bezogen und verweigert doppelte Handles für dieselbe Site. Shared-Slot-Blöcke verwenden denselben Block-Payload-Writer wie seiteneigene Blöcke, sodass sprachgebundene Texte in Übersetzungszeilen bleiben und gemeinsame Einstellungen auf dem Blockdatensatz-/Einstellungspfad verbleiben. Medienimport und Medienzuweisung bleiben außerhalb dieser Phase.

Seiten-Slot-Zuweisung

POST /webadmin/api/pages/{page}/slots/{slot}/shared-slot

Der Endpunkt weist einem bestehenden Seiten-Slot einen bestehenden kompatiblen aktiven Shared Slot derselben Site zu. Er erstellt keine fehlenden Seiten oder Slots. Er veröffentlicht die Seite nicht. Er verweigert site-übergreifende, inaktive und inkompatible Shared Slots. Er verweigert außerdem das Umschalten eines Slots, der noch seiteneigene Blöcke enthält, weil Phase 2A diese Blöcke nicht automatisch löscht oder ersetzt.

Content-Validate-/-Apply-Endpunkte

  • POST /webadmin/api/content/validate
  • POST /webadmin/api/content/apply

Sicherheit in Phase 1

  • nur Entwürfe
  • kein Veröffentlichen über Content-Apply
  • kein Überschreiben bestehender veröffentlichter Inhalte
  • kein breites Überschreiben bestehender Seiten oder Blöcke außerhalb von mode: replace_existing_draft_page
  • kein Remote-Fetch
  • kein Medien-Download oder -Import
  • noch keine Site-Erstellung
  • kein destruktives Löschen von Seiten über Content-Apply
  • kein destruktives Löschen von Blöcken außerhalb der transaktionsgebundenen Entwurfs-Slot-Ersetzung
  • noch keine Endpunkte zum Aktualisieren, Verschieben oder Löschen von Ressourcen
  • keine Browser-Session-, Formular- oder CSRF-Anforderung für JSON-Schreibvorgänge mit Bearer-Token
  • öffentlicher, nicht authentifizierter Zugriff ist auf die minimale Bootstrap-Antwort von GET /webadmin/api beschränkt

JSON-Fehlerformat

API-Fehler sind ausschließlich JSON. Sie dürfen nicht zum Login umleiten, keine CSRF-Seiten rendern und keine Stacktraces offenlegen. Übliche Felder:

{
  "ok": false,
  "code": "invalid_internal_api_token",
  "message": "Invalid internal API token.",
  "api_discovery_url": "/webadmin/api",
  "openapi_url": "/webadmin/api/openapi.json",
  "documentation_url": "/webadmin/api/ai-guide",
  "example_url": "/webadmin/api/examples/contact-page",
  "errors": []
}

Erwartete Statuscodes:

  • 401 für fehlende, ungültige oder widerrufene Tokens
  • 403 für fehlende Capabilities
  • 422 für Validierungsfehler

Beispiele für die Ressourcen-API

Seiten auflisten

GET /webadmin/api/pages

Seitendetails lesen

GET /webadmin/api/pages/{page}

Blöcke auflisten

GET /webadmin/api/blocks

Blockdetails lesen

GET /webadmin/api/blocks/{block}

Beispiel für Content-Validate/-Apply

Dieselbe Payload kann an beide Endpunkte übermittelt werden:

POST /webadmin/api/content/validate
POST /webadmin/api/content/apply

Beispiel eines englischen Marketing-Homepage-Entwurfs:

{
  "plan": {
    "site": "example-site",
    "locale": "en",
    "layout": "default",
    "page": {
      "title": "Acme Studio",
      "path": "/",
      "status": "draft"
    },
    "slots": {
      "main": [
        {
          "type": "hero",
          "translations": {
            "title": "Plan, build, and publish with confidence",
            "subtitle": "Structured content for modern teams",
            "content": "Create a draft homepage from a validated content plan."
          },
          "children": [
            {
              "type": "button_link",
              "translations": {
                "title": "Start planning"
              },
              "settings": {
                "url": "/contact",
                "variant": "primary"
              }
            }
          ]
        },
        {
          "type": "section",
          "children": [
            {
              "type": "container",
              "children": [
                {
                  "type": "grid",
                  "settings": {
                    "columns": 3
                  },
                  "children": [
                    {
                      "type": "card",
                      "children": [
                        {
                          "type": "card_body",
                          "children": [
                            {
                              "type": "plain_text",
                              "translations": {
                                "content": "Validate the whole draft before anything is written."
                              }
                            }
                          ]
                        }
                      ]
                    }
                  ]
                }
              ]
            }
          ]
        },
        {
          "type": "cta",
          "translations": {
            "title": "Ready to shape the next page?",
            "content": "Use structured plans for repeatable content creation."
          },
          "children": [
            {
              "type": "button_link",
              "translations": {
                "title": "Contact us"
              },
              "settings": {
                "url": "/contact",
                "variant": "primary"
              }
            }
          ]
        }
      ]
    }
  }
}

Validierungsregeln

  • Site-Handle oder -ID muss auflösbar sein
  • die Sprache (Locale) muss existieren und für die Ziel-Site aktiviert sein
  • das Layout muss existieren
  • ein Pfadkonflikt blockiert die Seitenerstellung
  • der Blocktyp muss veröffentlicht und nutzbar sein
  • die Kind-Unterstützung muss den Block-Verträgen folgen, sofern vorhanden
  • benutzerseitig sichtbarer Text gehört in Übersetzungszeilen
  • gemeinsame Einstellungen bleiben gemeinsam
  • unbekannte unsichere Einstellungen werden abgelehnt
  • harmlose unbekannte Einstellungen dürfen konsistent eine Warnung auslösen oder ignoriert werden
  • Apply validiert vor dem Schreiben erneut
  • Apply ist transaktional
  • Content-Apply lehnt weiterhin Veröffentlichen, Site-Erstellung, Medienimport, Remote-Fetch, nicht unterstütztes Überschreiben, nicht unterstütztes Ersetzen und Löschoperationen ab
  • Navigations- und Shared-Slot-Erstellung sind reine Erstellvorgänge, sofern eine spätere Phase keine expliziten entwurfssicheren Änderungsverträge hinzufügt

Antwortformat

Antworten sollten vorhersehbares JSON sein:

{
  "ok": true,
  "writes": [],
  "data": {
    "page": {
      "id": 123,
      "title": "Product Overview",
      "status": "draft",
      "edit_url": "/webadmin/pages/123/edit"
    }
  },
  "normalized_plan": {},
  "warnings": [],
  "errors": []
}

Validierungsfehler sollten einen Pfad und eine Meldung enthalten:

{
  "ok": false,
  "writes": [],
  "data": null,
  "normalized_plan": {},
  "warnings": [
    {
      "path": "plan.slots.main.1.settings.theme",
      "message": "Unknown harmless setting ignored."
    }
  ],
  "errors": [
    {
      "path": "plan.page.path",
      "message": "A page already exists at this path for the selected site and locale."
    }
  ]
}

Fügen Sie edit_url hinzu, wo es für erstellte oder aktualisierte CMS-Ressourcen nützlich ist.

Planabschnitte in Phase 2A

Content-Pläne dürfen navigation_menus, shared_slots und page_slot_shared_slots neben dem bestehenden Seiten-/Slot-Plan enthalten. validate schreibt nichts. apply schreibt alle gültigen Abschnitte in einer Transaktion und rollt den gesamten Plan zurück, wenn ein späterer Abschnitt fehlschlägt.

{
  "plan": {
    "site": "default",
    "locale": "en",
    "layout": "default",
    "page": {
      "title": "Homepage Draft",
      "path": "/",
      "status": "draft"
    },
    "slots": {
      "main": []
    },
    "navigation_menus": [
      {
        "handle": "primary",
        "label": "Primary Navigation",
        "items": [
          {
            "label": "Home",
            "url": "/",
            "target": "_self",
            "sort_order": 10
          }
        ]
      }
    ],
    "shared_slots": [
      {
        "handle": "site-header",
        "label": "Site Header",
        "slot": "header",
        "blocks": []
      }
    ],
    "page_slot_shared_slots": [
      {
        "page": "created",
        "slot": "header",
        "shared_slot": "site-header"
      }
    ]
  }
}

page_slot_shared_slots[].page kann sich mit created auf die im selben Plan erstellte Seite oder auf eine bestehende Seiten-ID beziehen. shared_slot kann sich auf einen früher im selben Plan erstellten Shared Slot oder auf ein bestehendes Shared-Slot-Handle derselben Site beziehen.

Zukünftige Phasen

Phase 2B

  • optionale entwurfssichere Update-/Verschiebe-Endpunkte für Navigations- und Shared-Slot-Blöcke
  • explizite sichere Leerungs-/Ersetzungsverträge, wo nötig
  • tiefere Header-/Navbar-Aufbauhelfer nur, wenn sie generisches CMS-Verhalten bleiben

Phase 3

  • Ressourcen-Endpunkte für entwurfssichere direkte Seiten-/Blockbearbeitungen, wo nötig
  • kontrollierte Entwurfs-Updates oder Ersetzen von Entwurfsinhalten
  • Seiten-Assets
  • Medien nur über bestehende Medien-IDs

Phase 4

  • zusätzliche explizite Workflow-Übergänge über das Veröffentlichen hinaus, wenn sie über eigenes Design und eigene Berechtigungen verfügen

Hinweise zur KI-Nutzung

  • zuerst Sites, Sprachen (Locales), Layouts und Blocktypen erkunden
  • vor dem Apply validieren
  • Entwurfsinhalte erstellen
  • strukturierte Blöcke aus docs/public-block-render-markup.md bevorzugen
  • Safe HTML nur als geprüften Fallback verwenden
  • generierte öffentliche Texte in der Zielsprache halten, etwa Englisch für eine englische Homepage

Grenzen

  • keine OpenAI- oder LLM-Integration im CMS-Kern
  • kein Crawling oder Fetching
  • kein beliebiger Import-/Export-Ersatz
  • kein automatisches Veröffentlichen
  • kein destruktives Löschen in Phase 1
  • keine Annahme einer Host-Route /admin
  • keine Verwendung des Routen-Präfixes /cms
  • kein QuizTem-spezifischer Laufzeitcode; die QuizTem-Homepage-Generierung ist ein späterer Consumer-Anwendungsfall für diese generische CMS-API