Internal Content API

Scopo

La Internal Content API è un'API sicura del CMS destinata a strumenti di IA e di operatore affidabili. Consente a questi strumenti di ispezionare i contratti di contenuto del CMS, creare contenuti partendo dalla bozza, sostituire specifici slot di proprietà della pagina su pagine in bozza esistenti ed eseguire operazioni di pubblicazione esplicite tramite JSON strutturato, senza accedere all'interfaccia di amministrazione nel browser, senza estrarne i dati e senza automatizzarla.

La fase 1 è implementata come un'API non pubblica, protetta da token e solo JSON, per l'individuazione dei contenuti in sola lettura e la creazione di pagine in bozza tramite piani di contenuto validati. La fase 2A aggiunge basi sicure per i menu di navigazione, gli Shared Slot e l'assegnazione esplicita di Shared Slot agli slot di pagina. La fase 2B aggiunge la sostituzione controllata, solo in bozza, del contenuto degli slot di proprietà della pagina su pagine esistenti. Gli endpoint di pubblicazione sono espliciti e richiedono content.publish; content apply resta orientato alla bozza e non pubblica. L'API rimane volutamente ristretta: nessun recupero remoto, nessuna eliminazione estesa di pagine tramite content apply, nessuna sostituzione degli slot basati su Shared Slot e nessuna pubblicazione a cascata degli Shared Slot.

Posizionamento del prodotto

La Internal Content API è:

  • un'API del CMS interna/per operatori
  • protetta da token
  • non pubblica
  • non un'API di delivery per CMS headless
  • non un sostituto dei permessi di amministrazione
  • non un sostituto di import/export
  • non un'integrazione con un fornitore di IA

Il core del CMS dovrebbe essere il proprietario di questa API perché opera su concetti di contenuto del core: siti, pagine, layout, slot, blocchi, traduzioni, navigazione e shared slot. Gli strumenti di IA o di operatore possono chiamare l'API, ma il core del CMS non deve incorporare logiche di integrazione con OpenAI, LLM, crawler o fornitori specifici.

Prefisso di rotta

Il prefisso canonico è:

/webadmin/api

In questo modo l'API resta entro il confine di amministrazione del CMS pur usando un segmento API conciso e familiare. Gli endpoint in stile risorsa dovrebbero trovarsi direttamente sotto questo prefisso, come /webadmin/api/pages e /webadmin/api/blocks.

L'individuazione dell'API parte da:

GET /webadmin/api

I chiamanti non autenticati ricevono soltanto il JSON di bootstrap sicuro per il pubblico. I chiamanti autenticati ricevono metadati sicuri sulla versione del prodotto oltre ai link a OpenAPI, alla guida per l'IA, al contratto di contenuto, agli esempi, a content validate/apply, alle pagine, alla navigazione e agli Shared Slot. Gli strumenti esterni di IA/operatore dovrebbero partire da questa risposta di discovery in tempo reale invece di leggere il repository del CMS o la documentazione locale del pacchetto.

Le operazioni di contenuto basate su piani usano:

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

Scelte di rotta da evitare:

  • /webadmin/internal-api, perché inutilmente prolisso
  • /webadmin/api/content-plans/..., perché content-plans è troppo tecnico e ristretto per il contratto dell'URL
  • collocare ogni risorsa sotto /webadmin/api/content/..., perché le API di risorsa devono restare chiare e dirette
  • /admin, perché il CMS non deve presumere che il percorso /admin del prodotto ospite gli appartenga
  • /cms, perché /cms resta riservato ai soli asset statici del CMS

Autenticazione

L'API usa l'autenticazione con token Bearer:

Authorization: Bearer <token>

I token dell'API del CMS vengono creati da un super amministratore del CMS da System -> API Tokens. Il CMS memorizza soltanto un hash SHA-256 e un'anteprima sicura nella tabella di database cms_api_tokens. Il token in chiaro viene mostrato una sola volta subito dopo la creazione e non viene più mostrato.

I super amministratori possono revocare un token per disabilitare immediatamente l'accesso all'API mantenendo visibile la riga di audit, oppure eliminare un token per rimuoverne definitivamente il record dall'elenco. Anche l'eliminazione di un token attivo disabilita subito l'accesso all'API, perché l'autenticatore non trova più un hash memorizzato corrispondente.

Gli strumenti locali di IA e di operatore dovrebbero conservare il token generato in un archivio di segreti affidabile dell'operatore.

Usate l'URL di base della Internal Content API nella configurazione locale dell'operatore:

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

Il runtime del CMS non richiede WEBBLOCKS_CMS_INTERNAL_API_TOKEN.

Regole di autenticazione:

  • i token mancanti, errati o revocati restituiscono un 401 JSON
  • i token revocati smettono di funzionare immediatamente
  • i token non devono mai comparire in log, diagnostica, report di supporto, test o esempi di documentazione
  • il confronto dei token deve usare un confronto a tempo costante
  • le richieste API riuscite aggiornano last_used_at e last_used_ip del token
  • le richieste API riuscite memorizzano anche uno user-agent troncato come contesto di audit per l'operatore
  • le risposte sono esclusivamente JSON

Esempio di richiesta:

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

Capability

I super amministratori scelgono le capability del token quando lo creano da System -> API Tokens e possono in seguito modificarne nome e capability senza esporre o ruotare il segreto del token. La discovery espone le capability salvate senza restituire il valore del token, il suo hash o la sua anteprima. I token standard per la costruzione di pagine hanno per impostazione predefinita queste capability:

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

Le capability distruttive e di pubblicazione sono opzioni avanzate separate e non sono selezionate per impostazione predefinita:

  • content.publish
  • pages.delete

Gli endpoint di scrittura verificano la capability pertinente lato server. Le capability mancanti restituiscono un 403 JSON con le indicazioni di api_discovery_url, openapi_url, documentation_url ed example_url. I normali token per la costruzione di pagine non dovrebbero includere capability distruttive.

Modello dell'API

L'API ha due modalità complementari.

Resource API

Gli endpoint di risorsa rispecchiano le singole operazioni equivalenti a quelle dell'amministrazione:

  • elencare e leggere le pagine
  • elencare e leggere i blocchi
  • elencare siti, lingue (locale), layout e tipi di blocco
  • in seguito, creare o aggiornare direttamente risorse di pagina in bozza
  • in seguito, elencare o garantire gli slot di pagina
  • in seguito, aggiungere, aggiornare, spostare ed eliminare blocchi tramite endpoint di risorsa
  • in seguito, aggiungere blocchi figli tramite endpoint di risorsa
  • in seguito, gestire navigazione e shared slot

Endpoint di risorsa della fase 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

Gli endpoint content validate/apply gestiscono piani di contenuto completi in più passaggi:

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

validate verifica un piano di contenuto completo e non scrive nulla. apply valida di nuovo il piano e poi crea in modo transazionale la pagina in bozza richiesta, le voci di navigazione, gli Shared Slot, gli alberi di blocchi degli Shared Slot e le assegnazioni di Shared Slot agli slot di pagina. Può inoltre sostituire slot specifici di proprietà della pagina su una pagina in bozza esistente quando il piano usa mode: replace_existing_draft_page e include una protezione ottimistica. È utile per pagine generate dall'IA, template, pagine iniziali, header/footer condivisi e strumenti di migrazione, casi in cui il CMS deve evitare contenuti creati a metà.

Il corpo della richiesta può ancora contenere un campo plan o un altro payload strutturato di piano di contenuto. L'URL deve restare /content/validate e /content/apply.

Servono entrambe le modalità:

  • la Resource API espone agli strumenti interni il modello di contenuto e i contratti già esistenti del CMS
  • la Content Validate / Apply API evita scritture parziali durante costruzioni di pagina più ampie

Sostituzione di slot su pagine in bozza esistenti

La sostituzione su pagine in bozza esistenti resta all'interno del contratto validate/apply:

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

Usate mode: replace_existing_draft_page per sostituire uno o più slot di proprietà della pagina su una pagina in bozza esistente. L'operazione richiede content.validate per la validazione e content.apply per l'applicazione. Non richiede pages.delete, perché non è un'operazione generale di eliminazione di pagine.

Il path della Page Translation è l'URL pubblico canonico. I nuovi piani dovrebbero usare percorsi come /contact, /features o /docs/internal-content-api; /p/... è solo compatibilità legacy. I percorsi con barre vengono normalizzati segmento per segmento, così /docs/internal-content-api/ diventa /docs/internal-content-api e non viene compresso in docsinternal-content-api. Aree di rotta riservate come /webadmin, /webadmin/api, /cms, /search, /search.json, /contact-messages, /install e le rotte di autenticazione dell'host non possono essere create come percorsi pubblici di pagina.

Esempio:

{
  "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."
          }
        }
      ]
    }
  }
}

Regole:

  • la pagina di destinazione deve essere in stato draft
  • è richiesto expected_path oppure expected_updated_at
  • expected_path usa il percorso pubblico canonico della Page Translation, non un alias legacy /p/...
  • la pagina di destinazione deve appartenere al sito richiesto e la lingua (locale) deve essere abilitata per quel sito
  • ogni slot deve esistere sulla pagina e usare blocchi di proprietà della pagina
  • gli slot basati su Shared Slot vengono rifiutati anziché svuotati
  • vengono rimossi solo i blocchi presenti nei replace_slots indicati
  • i vecchi blocchi vengono rimossi e i nuovi scritti in un'unica transazione
  • le revisioni di pagina vengono acquisite prima e dopo l'applicazione
  • non avvengono pubblicazione, recupero/importazione di media, eliminazioni estese o rimozione delle assegnazioni di Shared Slot

Metadati di sincronizzazione della sorgente

I piani di contenuto possono conservare un oggetto source_sync limitato e privo di segreti per i flussi di sincronizzazione della documentazione IA/operatore. Le impostazioni di pagina arbitrarie vengono rifiutate. La forma accettata è:

{
  "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 salva questi metadati nelle impostazioni della pagina e le risposte API di elenco/dettaglio delle pagine espongono gli stessi campi di source_sync ammessi, per confronti futuri. Non includete token, valori d'ambiente, percorsi assoluti locali o del server, né altri segreti.

Endpoint di pubblicazione espliciti

La pubblicazione è separata da content apply e richiede un token con content.publish.

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

POST /webadmin/api/pages/{page}/publish pubblica il record della pagina. Il suo payload predefinito riguarda solo la pagina:

{
  "include_page_owned_blocks": false
}

Regole:

  • omettere include_page_owned_blocks equivale a false
  • include_page_owned_blocks: false pubblica solo il record della pagina e lascia invariati i blocchi in bozza o in revisione
  • include_page_owned_blocks: true pubblica i blocchi in bozza e in revisione appartenenti agli slot di pagina non condivisi, inclusi i blocchi figli annidati
  • i blocchi già pubblicati restano invariati
  • gli slot basati su Shared Slot sono esclusi e segnalati nella risposta
  • i campi di cascata degli Shared Slot non supportati, come publish_shared_slots, include_shared_slot_blocks o shared_slot_cascade, restituiscono un 422 JSON
  • la risposta include i metadati di id/stato/percorso della pagina, l'indicazione se i blocchi di proprietà della pagina sono stati inclusi, il numero di blocchi pubblicati, i riepiloghi degli Shared Slot esclusi e l'id della revisione di pagina

POST /webadmin/api/pages/{page}/publish-page-owned-blocks pubblica soltanto i blocchi di proprietà della pagina non ancora pubblicati e non modifica lo stato del flusso di lavoro della pagina. Usa la stessa capability content.publish e la stessa regola di esclusione degli Shared Slot.

Gli strumenti di IA/operatore non devono presumere che la pubblicazione della pagina renda pubblico tutto il contenuto dei blocchi. Usate include_page_owned_blocks: true solo quando l'utente ha approvato esplicitamente la pubblicazione di tutti i blocchi non pubblicati di proprietà di quella pagina. Il contenuto degli Shared Slot va rivisto e pubblicato separatamente.

Endpoint del contratto di contenuto

GET /webadmin/api/content-contract è un endpoint di discovery in sola lettura per strumenti di IA/operatore affidabili. Restituisce il prefisso dell'API, gli URL di validate/apply, il modello di URL per l'anteprima di amministrazione, i flag di sicurezza, gli URL di discovery, i pattern consigliati per costruire le pagine e i metadati sanificati dei contratti di blocco.

L'endpoint è comportamento generico del prodotto CMS. Non deve restituire segreti specifici dell'installazione, valori dei token, contenuti Blade grezzi, percorsi assoluti del filesystem, percorsi privati del server o istruzioni specifiche di un sito. Le righe del contratto di blocco possono includere handle/slug, etichetta, categoria, stato, supporto a container e figli, campi traducibili, campi di impostazioni condivise e comportamento della radice del renderer pubblico.

Gli strumenti di IA dovrebbero chiamare questo endpoint o GET /webadmin/api/block-types prima di costruire un piano e devono usare soltanto gli handle presenti nell'installazione corrente.

Il contratto di contact_form include ulteriori metadati sicuri del form: schema delle impostazioni, campi tradotti, l'endpoint pubblico di invio POST /contact-messages, il comportamento CSRF richiesto nel browser, le regole di validazione lato server, il campo di controllo antispam nascosto e generato dal CMS, il comportamento generico di successo di tale campo, le note su classificazione/quarantena dello spam, il salvataggio prima della notifica, l'ordine di fallback dei destinatari, la registrazione sicura dei fallimenti di notifica e il comportamento di revisione di /webadmin/contact-messages. Il campo di controllo è generato dal renderer, non fa parte del normale input del visitatore e non deve essere creato manualmente dall'API né dagli strumenti di IA/operatore. Gli strumenti per le pagine di contatto dovrebbero usare quel blocco nativo anziché Trusted HTML, markup di form grezzo o form mailto:. Il vecchio campo website non fa più parte del contratto pubblico del Contact Form.

La guida leggibile AI Page Building Guide è distribuita nelle installazioni native da pacchetto in vendor/fklavyenet/webblocks-cms/docs/ai-page-building-guide.md.

Ambito della fase 1

Endpoint di discovery

  • 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

Endpoint delle pagine

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

Endpoint dei blocchi

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

Endpoint della navigazione

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

I menu di navigazione usano il modello esistente del CMS navigation_items.menu_key. La fase 2A supporta gli handle di menu forniti dal CMS, come primary, footer, mobile, legal e docs; non aggiunge una tabella di menu separata. Creare un menu di navigazione equivale a creare un gruppo di menu sicuro con ambito di sito, con voci iniziali opzionali. Il sistema rifiuta di sovrascrivere un sito/menu che contiene già voci.

Gli URL delle voci di navigazione possono essere percorsi interni come /, /about e /contact, oppure URL sicuri http/https. L'API rifiuta javascript:, data:, gli URL relativi al protocollo, i percorsi di traversal, gli URL malformati, i target non supportati e le etichette vuote. Gli endpoint di navigazione non creano pagine, non pubblicano pagine, non effettuano crawling dei siti e non recuperano URL remoti.

Endpoint degli Shared Slot

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

La creazione di Shared Slot ha ambito di sito e rifiuta handle duplicati all'interno dello stesso sito. I blocchi degli Shared Slot riutilizzano lo stesso writer di payload usato dai blocchi di proprietà della pagina, perciò i testi propri di ciascuna lingua restano nelle righe di traduzione e le impostazioni condivise rimangono sul record del blocco / percorso delle impostazioni. L'importazione e l'assegnazione dei media restano fuori da questa fase.

Assegnazione degli slot di pagina

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

L'endpoint assegna a uno slot di pagina esistente uno Shared Slot già esistente, attivo, compatibile e dello stesso sito. Non crea pagine o slot mancanti. Non pubblica la pagina. Rifiuta gli Shared Slot di altri siti, inattivi o incompatibili. Rifiuta inoltre di cambiare uno slot che contiene ancora blocchi di proprietà della pagina, perché la fase 2A non elimina né sostituisce automaticamente quei blocchi.

Endpoint Content Validate / Apply

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

Sicurezza della fase 1

  • solo bozze
  • nessuna pubblicazione tramite content apply
  • nessuna sovrascrittura di contenuti pubblicati esistenti
  • nessuna sovrascrittura estesa di pagine o blocchi esistenti al di fuori di mode: replace_existing_draft_page
  • nessun recupero remoto
  • nessun download o importazione di media
  • nessuna creazione di siti per ora
  • nessuna eliminazione distruttiva di pagine tramite content apply
  • nessuna eliminazione distruttiva di blocchi al di fuori della sostituzione degli slot in bozza con ambito di transazione
  • nessun endpoint di aggiornamento, spostamento o eliminazione di risorse per ora
  • nessun requisito di sessione browser, form o CSRF per le scritture JSON con token Bearer
  • l'accesso pubblico non autenticato è limitato alla risposta minima di bootstrap di GET /webadmin/api

Forma degli errori JSON

Gli errori dell'API sono esclusivamente JSON. Non devono reindirizzare al login, mostrare pagine CSRF o esporre stack trace. Campi comuni:

{
  "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": []
}

Stati previsti:

  • 401 per token mancanti, non validi o revocati
  • 403 per capability mancanti
  • 422 per errori di validazione

Esempi di Resource API

Elencare le pagine

GET /webadmin/api/pages

Leggere i dettagli di una pagina

GET /webadmin/api/pages/{page}

Elencare i blocchi

GET /webadmin/api/blocks

Leggere i dettagli di un blocco

GET /webadmin/api/blocks/{block}

Esempio di Content Validate / Apply

Lo stesso payload può essere inviato a entrambi gli endpoint:

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

Esempio di bozza di homepage marketing in inglese:

{
  "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"
              }
            }
          ]
        }
      ]
    }
  }
}

Regole di validazione

  • l'handle o l'ID del sito deve risolversi
  • la lingua (locale) deve esistere ed essere abilitata per il sito di destinazione
  • il layout deve esistere
  • un conflitto di path impedisce la creazione della pagina
  • il tipo di blocco deve essere pubblicato e utilizzabile
  • il supporto ai figli deve rispettare i contratti dei blocchi, dove disponibili
  • i testi rivolti all'utente appartengono alle righe di traduzione
  • le impostazioni condivise restano condivise
  • le impostazioni sconosciute non sicure vengono rifiutate
  • le impostazioni sconosciute innocue possono generare un avviso o essere ignorate in modo coerente
  • apply valida di nuovo prima di scrivere
  • apply è transazionale
  • Content apply continua a rifiutare pubblicazione, creazione di siti, importazione di media, recupero remoto, sovrascritture non supportate, sostituzioni non supportate e operazioni di eliminazione
  • la creazione di navigazione e Shared Slot è di sola creazione, a meno che una fase successiva non aggiunga contratti di mutazione espliciti e sicuri per le bozze

Forma della risposta

Le risposte devono essere JSON prevedibile:

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

Gli errori di validazione devono includere un path e un messaggio:

{
  "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."
    }
  ]
}

Includete edit_url dove è utile per le risorse CMS create o aggiornate.

Sezioni del piano della fase 2A

I piani di contenuto possono includere navigation_menus, shared_slots e page_slot_shared_slots accanto al piano pagina/slot già esistente. validate non scrive nulla. apply scrive tutte le sezioni valide in un'unica transazione e annulla l'intero piano quando una sezione successiva fallisce.

{
  "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 può fare riferimento alla pagina creata dallo stesso piano usando created, oppure all'ID di una pagina esistente. shared_slot può fare riferimento a uno Shared Slot creato prima nello stesso piano o all'handle di uno Shared Slot esistente dello stesso sito.

Fasi future

Fase 2B

  • endpoint opzionali di aggiornamento/spostamento sicuri per le bozze, per la navigazione e i blocchi degli Shared Slot
  • contratti espliciti di svuotamento/sostituzione sicuri dove necessario
  • helper più avanzati per la costruzione di header/navbar, solo se restano comportamento generico del CMS

Fase 3

  • endpoint di risorsa per modifiche dirette a pagine/blocchi sicure per le bozze, dove necessario
  • aggiornamenti controllati delle bozze o sostituzione del contenuto in bozza
  • asset di pagina
  • media solo tramite ID di media esistente

Fase 4

  • ulteriori transizioni esplicite del flusso di lavoro oltre alla pubblicazione, quando hanno progettazione e permessi propri

Indicazioni per l'uso con l'IA

  • individuate prima siti, lingue (locale), layout e tipi di blocco
  • validate prima di applicare
  • create contenuti in bozza
  • preferite i blocchi strutturati indicati in docs/public-block-render-markup.md
  • evitate Safe HTML se non come ripiego verificato
  • mantenete i testi pubblici generati nella lingua di destinazione, ad esempio l'inglese per una homepage in inglese

Confini

  • nessuna integrazione OpenAI o LLM nel core del CMS
  • nessun crawling o recupero di contenuti
  • nessuna sostituzione arbitraria di import/export
  • nessuna pubblicazione automatica
  • nessuna eliminazione distruttiva nella fase 1
  • nessun presupposto sulla rotta /admin dell'host
  • nessun uso del prefisso di rotta /cms
  • nessun codice runtime specifico di QuizTem; la generazione della homepage di QuizTem è un caso d'uso successivo di questa API CMS generica