From 9be524faf249093c50904392f1d6b5eea5e79b78 Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Thu, 17 Sep 2026 13:12:03 +0200 Subject: [PATCH 01/31] Start documenting Headless Page Builder --- .../field_type_reference/pagefield.md | 6 + .../img/page-edit-headless.png | Bin 0 -> 46644 bytes .../pages/headless_page_builder.md | 223 ++++++++++++++++++ docs/content_management/pages/pages.md | 1 + mkdocs.yml | 1 + 5 files changed, 231 insertions(+) create mode 100644 docs/content_management/img/page-edit-headless.png create mode 100644 docs/content_management/pages/headless_page_builder.md diff --git a/docs/content_management/field_types/field_type_reference/pagefield.md b/docs/content_management/field_types/field_type_reference/pagefield.md index b8497dc0d2b..c90a4b046cb 100644 --- a/docs/content_management/field_types/field_type_reference/pagefield.md +++ b/docs/content_management/field_types/field_type_reference/pagefield.md @@ -72,3 +72,9 @@ As a whole a sample layout could look as follows: ``` html+twig [[= include_file('code_samples/page/pagefield_layout.html.twig') =]] ``` + +### Headless rendering + +When used headless, the front-end have to fetch the page data and render the zones and blocks by itself. +It's also possible for the front-end to provide a URL that can communicate with the Page Builder and display a preview in it. +See [Headless front-end preview in Page Builder](headless_page_builder.md) for more information. diff --git a/docs/content_management/img/page-edit-headless.png b/docs/content_management/img/page-edit-headless.png new file mode 100644 index 0000000000000000000000000000000000000000..ebd239930c0501c081d20ff753e355eacc2d787b GIT binary patch literal 46644 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 D)kYs% literal 0 HcmV?d00001 diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md new file mode 100644 index 00000000000..f7524da5117 --- /dev/null +++ b/docs/content_management/pages/headless_page_builder.md @@ -0,0 +1,223 @@ +--- +description: The Page Builder can preview pages outside the DXP. +edition: experience +month_change: true +--- + +# Headless front-end preview in Page Builder + +The Page Builder can preview pages hosted outside the DXP. + +You provide a single URL for the front-end page and let it communicate with the Page Builder using the JavaScript message API. + +The usage of this front-end page instead of the DXP one is set per content type. TODO: This is on-prem only, SaaS don't have the choice + +## Configuration TODO: How this is declared on Saas? + +First, set up the feature, for example, in `config/packages/ibexa_page_builder.yaml`: + +```yaml +ibexa: + system: + admin_group: + page_builder: + headless: + enabled: true + base_url: 'https://example.com/page.html' # The front-end URL loaded by the Page Builder's iframe +``` + +Then, edit the content types with Landing page field type that are used headless, +edit that field, and check the option "Edit in the headless Page Builder". + +![Checked "Edit in the headless Page Builder"](page-edit-headless.png) + +## Communication protocol + +The front-end resource targeted by `base_url` is loaded by the Page Builder when editing a content having a Landing page field "Edit in the headless Page Builder" enabled. +This resource must follow a protocol to communicate with the Page Builder from the iframe is loaded in. +This protocol is based on the JavaScript message API. + +The Page Builder sends messages to the framed front-end resource. +They can be received by listening the [message event](https://developer.mozilla.org/en-US/docs/Web/API/EventSource/message_event). + +The front-end resource sends back messages to the Page Builder. +They can be sent using the [`postMessage()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) method. +The target origin of those messages must be the Page Builder's origin. + +```js +const pbOrigin = 'https://admin.example.com/'; +window.parent.postMessage(message, pbOrigin); +``` + +Those messages are JS objects with the following structure: + +```js +let message = { + type: 'PREFIX:MESSAGE_TYPE', + data: {} +}; +``` + +The `PREFIX` sort message types by their sender. +`PB:` for messages sent by the Page Builder, `APP:` for messages sent by the front-end resource. + +The data depends on the message type. + +Message types are then sorted by capabilities. +So the front-end can declare which capabilities it supports and the Page Builder can refrain from sending or expecting unsupported messages. + +### Message types and capabilities + +| Capability | Message type | Description | +|------------------|---------------------------|-----------------------------------------------------------------------------------------------------------| +| (handshake) | APP:INITIALIZED | To establish the communication and declare which protocol version and capabilities are supported. | +| (handshake) | PB:INIT_MODE | To validate the communication and give information about the edited content draft. | +| (core) | PB:UPDATE_FIELD_DATA | To notify that the field has changed, like when a block have been edited or the layout has been switched. | +| (core) | PB:DISPATCH_EVENT | To help converting message into custom event. TODO | +| blocks.dnd | PB:DRAG_START_PREVIEW | TODO | +| blocks.dnd | PB:DRAG_OVER | To give the position of the mouse while a new block is dragged. | +| blocks.dnd | PB:DRAG_END_PREVIEW | TODO | +| blocks.dnd | PB:DROP | To notify that a new block has been dropped. | +| blocks.dnd | APP:DROP_RESPONSE | To notify that the drop action has been processed and declare which zone welcomed the new block. | +| blocks.dnd | PB:SCROLL_BY | TODO | +| blocks.geometry | APP:POSITIONS_UPDATE | To declare the actual position of the blocks (so the block editing menus can be positionned). | +| blocks.geometry | APP:SCROLL_END | TODO | +| blocks.remove | PB:BLOCK_REMOVE | TODO | +| blocks.remove | APP:BLOCK_REMOVE_RESPONSE | TODO | +| blocks.remove | APP:BLOCK_REMOVE_REQUEST | TODO | +| blocks.reveal | PB:SCROLL_INTO_BLOCK | TODO | +| blocks.select | APP:BLOCK_CLICKED | To notify that a block has been clicked. | +| pointer.tracking | APP:MOUSE_POSITION | To declare the actual position of the mouse (so the block editing menus can be displayed on hover). | +| preview.params | PB:UPDATE_PREVIEW_PARAMS | TODO | + +### Communication initialization + +First, the front-end send an initialization message to the Page Builder, indicating which version of the protocol and which capabilities are supported: + +```js +const initializedMessage = { + type: 'APP:INITIALIZED', + data: { + protocol: { + supported: [1] + }, + capabilities: [ + 'blocks.dnd', + 'blocks.geometry', + 'blocks.select', + 'pointer.tracking', + // … + ], + } +}; +``` + +The Page Builder replies with a confirmation message. +The initialization message might be sent several times until the Page Builder replies to it. + +This confirmation `data` contains: +- the actual version of the protocol used (`protocol.version`) and the other supported versions (`protocol.supported`). +- a list of all available capabilities (`capabilities`) +- a list of the existing block types, their attributes, and their configuration (`blocksConfig`) +- information about the actually edited content draft (`intentParameters`) +- the current value of the Landing page field being edited (`fieldValue`) including the layout, zones, and blocks. +- a block ID to name mapping (`blocksIdMap`) +- a list of translations for the front-end to use (`translations`) + +```json +{ + "type": "PB:INIT_MODE", + "data": { + "protocol": { + "version": 1, + "supported": [ + 1 + ] + }, + "capabilities": [ + "blocks.dnd", + "blocks.geometry", + "blocks.remove", + "blocks.reveal", + "blocks.select", + "pointer.tracking", + "preview.params" + ], + "blocksConfig": [ + { + "type": "block_type", + "name": "Block type name", + "category": "Block category", + "thumbnail": "path/to/block/thumbnail.file", + "visible": true, + "views": { + "default": { + "name": "Default" + } + }, + "attributes": [ + { + "id": "attribute_id", + "name": "Attribute name", + "type": "attribute_type", + "value": null, + "constraints": { + "not_blank": { + "message": "Please select…" + } + } + } + ] + } + ], + "intentParameters": { + "locationId": "2", + "contentId": 52, + "versionNo": 6, + "languageCode": "eng-GB" + }, + "fieldValue": { + "layout": "ibexa_fieldtype_page.layouts..identifier", + "zones": [ + { + "id": "123", + "name": "ibexa_fieldtype_page.layouts..zones..name", + "blocks": [ + { + "visible": true, + "id": "456", + "type": "block_type", + "name": "Block name", + "view": "default", + "class": null, + "style": null, + "compiled": "", + "since": null, + "till": null, + "attributes": [ + { + "id": "789", + "name": "attribute_name", + "value": "…" + } + ] + } + ] + } + ] + }, + "blocksIdMap": { + "456": "Block name" + }, + "translations": { + "block.attribute.invalid": "%name% is invalid", + "block.no_availability.content": "You have to delete it to publish", + "block.no_availability.delete": "Delete", + "block.no_availability.title": "This element is not available in this page", + "block.unknown.type": "Unknown block type: %type% (block name: %name%)", + "drag.drop.blocks.here": "Drag and drop blocks here", + "structure.drop.zone": "Drop zone %number%" + } + } +} +``` diff --git a/docs/content_management/pages/pages.md b/docs/content_management/pages/pages.md index f5fb0af210f..71da6027254 100644 --- a/docs/content_management/pages/pages.md +++ b/docs/content_management/pages/pages.md @@ -14,4 +14,5 @@ Pages are block-based special types of content that editors can create and modif "content_management/pages/page_block_attributes", "content_management/pages/page_block_validators", "content_management/pages/create_custom_page_block", + "content_management/pages/headless_page_builder", ], columns=3) =]] diff --git a/mkdocs.yml b/mkdocs.yml index 1b8db944909..ea1bdc80524 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -214,6 +214,7 @@ nav: - Create custom Page block: content_management/pages/create_custom_page_block.md - React App page block: content_management/pages/react_app_block.md - Ibexa Connect scenario block: content_management/pages/ibexa_connect_scenario_block.md + - Headless Page Builder: content_management/pages/headless_page_builder.md - Forms: - Forms: content_management/forms/forms.md - Form Builder guide: content_management/forms/form_builder_guide.md From f611a092d87078109c125c6c80d654ec2a686a1f Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Thu, 17 Sep 2026 17:40:40 +0200 Subject: [PATCH 02/31] Continue documenting Headless Page Builder --- .../pages/headless_page_builder.md | 121 ++++++++++++++---- 1 file changed, 98 insertions(+), 23 deletions(-) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index f7524da5117..f89c3a3d66b 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -68,27 +68,29 @@ So the front-end can declare which capabilities it supports and the Page Builder ### Message types and capabilities -| Capability | Message type | Description | -|------------------|---------------------------|-----------------------------------------------------------------------------------------------------------| -| (handshake) | APP:INITIALIZED | To establish the communication and declare which protocol version and capabilities are supported. | -| (handshake) | PB:INIT_MODE | To validate the communication and give information about the edited content draft. | -| (core) | PB:UPDATE_FIELD_DATA | To notify that the field has changed, like when a block have been edited or the layout has been switched. | -| (core) | PB:DISPATCH_EVENT | To help converting message into custom event. TODO | -| blocks.dnd | PB:DRAG_START_PREVIEW | TODO | -| blocks.dnd | PB:DRAG_OVER | To give the position of the mouse while a new block is dragged. | -| blocks.dnd | PB:DRAG_END_PREVIEW | TODO | -| blocks.dnd | PB:DROP | To notify that a new block has been dropped. | -| blocks.dnd | APP:DROP_RESPONSE | To notify that the drop action has been processed and declare which zone welcomed the new block. | -| blocks.dnd | PB:SCROLL_BY | TODO | -| blocks.geometry | APP:POSITIONS_UPDATE | To declare the actual position of the blocks (so the block editing menus can be positionned). | -| blocks.geometry | APP:SCROLL_END | TODO | -| blocks.remove | PB:BLOCK_REMOVE | TODO | -| blocks.remove | APP:BLOCK_REMOVE_RESPONSE | TODO | -| blocks.remove | APP:BLOCK_REMOVE_REQUEST | TODO | -| blocks.reveal | PB:SCROLL_INTO_BLOCK | TODO | -| blocks.select | APP:BLOCK_CLICKED | To notify that a block has been clicked. | -| pointer.tracking | APP:MOUSE_POSITION | To declare the actual position of the mouse (so the block editing menus can be displayed on hover). | -| preview.params | PB:UPDATE_PREVIEW_PARAMS | TODO | +The handshake and core messages are mandatory and not related to an optional capability. + +| Capability | Message type | Description | +|------------------|----------------------------------------------------|-----------------------------------------------------------------------------------------------------------| +| (handshake) | [`APP:INITIALIZED`](#communication-initialization) | To establish the communication and declare which protocol version and capabilities are supported. | +| (handshake) | [`PB:INIT_MODE`](#communication-initialization) | To validate the communication and give information about the edited content draft. | +| (core) | [`PB:UPDATE_FIELD_DATA`](#on-field-update) | To notify that the field has changed, like when a block have been edited or the layout has been switched. | +| (core) | [`PB:DISPATCH_EVENT`](##re-dispatching-events) | TODO: To notify of event that should be dispached | +| blocks.dnd | [`PB:DRAG_START_PREVIEW`](#drag-and-drop) | To notify that an existing block starts being dragged in the preview. | +| blocks.dnd | [`PB:DRAG_OVER`](#drag-and-drop) | To give the position of the mouse while a block is dragged. | +| blocks.dnd | [`PB:DRAG_END_PREVIEW`](#drag-and-drop) | To notify that an existing block stopped being dragged in the preview. | +| blocks.dnd | [`PB:DROP`](#drag-and-drop) | To notify that a block has been dropped. | +| blocks.dnd | [`APP:DROP_RESPONSE`](#drag-and-drop) | To notify that the drop action has been processed and declare which zone welcomed the block. | +| blocks.dnd | [`PB:SCROLL_BY`](#drag-and-drop) | TODO | +| blocks.geometry | APP:POSITIONS_UPDATE | To declare the actual position of the blocks (so the block editing menus can be positionned). | +| blocks.geometry | APP:SCROLL_END | TODO | +| blocks.remove | PB:BLOCK_REMOVE | TODO | +| blocks.remove | APP:BLOCK_REMOVE_RESPONSE | TODO | +| blocks.remove | APP:BLOCK_REMOVE_REQUEST | TODO | +| blocks.reveal | PB:SCROLL_INTO_BLOCK | TODO | +| blocks.select | APP:BLOCK_CLICKED | To notify that a block has been clicked. | +| pointer.tracking | APP:MOUSE_POSITION | To declare the actual position of the mouse (so the block editing menus can be displayed on hover). | +| preview.params | PB:UPDATE_PREVIEW_PARAMS | TODO | ### Communication initialization @@ -116,12 +118,12 @@ The Page Builder replies with a confirmation message. The initialization message might be sent several times until the Page Builder replies to it. This confirmation `data` contains: -- the actual version of the protocol used (`protocol.version`) and the other supported versions (`protocol.supported`). +- the actual version of the protocol used (`protocol.version`) and the other supported versions (`protocol.supported`) - a list of all available capabilities (`capabilities`) - a list of the existing block types, their attributes, and their configuration (`blocksConfig`) - information about the actually edited content draft (`intentParameters`) - the current value of the Landing page field being edited (`fieldValue`) including the layout, zones, and blocks. -- a block ID to name mapping (`blocksIdMap`) +- a block-ID-to-name mapping (`blocksIdMap`) - a list of translations for the front-end to use (`translations`) ```json @@ -221,3 +223,76 @@ This confirmation `data` contains: } } ``` + +### On field update + +The `PB:UPDATE_FIELD_DATA` message is sent from the Page Builder to the front-end resource when the Landing page field value is updated. + +Its data contains the new value of the field with the following structure: +- a list of the existing block types, their attributes, and their configuration (`blocksConfig`) +- the current value of the Landing page field being edited (`fieldValue`) including the layout, zones, and blocks. +- a block-ID-to-name mapping (`blocksIdMap`) +- a list of Ids from the new blocks that have been added (`highlightedBlockIds`) + +```json +{ + "type": "PB:UPDATE_FIELD_DATA", + "data": { + "blocksConfig": [], + "fieldValue": { + "layout": "…", + "zones": [] + }, + "blocksIdMap": {}, + "highlightedBlockIds": [] + } +} +``` + +### Re-dispatching events + +The `PB:DISPATCH_EVENT` message is sent from the Page Builder to the front-end resource for being re-dispatched there as a custom event. + +```js +window.addEventListener('message', (messageEvent) => { + switch (messageEvent.data.type) { + case 'PB:DISPATCH_EVENT': + document.body.dispatchEvent(new CustomEvent(messageEvent.data.data.eventName, { detail: messageEvent.data.data.eventDetail })); + break; + } +}); +``` + +TODO: Available events +- `ibexa-active-block-clicked`? +- `ibexa-post-update-blocks-preview`? + +### Drag and drop (`blocks.dnd`) + +`PB:DRAG_OVER` message is sent from the Page Builder to the front-end preview to give the position of the mouse while a (new or existing) block is dragged. + +`PB:DRAG_START_PREVIEW` and `PB:DRAG_END_PREVIEW` are sent at the beginning and at the end of a drag operation on an existing block in the front-end preview. +Its data contains the ID of the block being dragged (`blockId`). + +`PB:DROP` message is sent from the Page Builder to the front-end preview to notify that a block has been dropped. +It has no data. Combined with the last `PB:DRAG_OVER` message, the front-end can determine where the block has been dropped. + +`APP:DROP_RESPONSE` message is sent from the front-end preview to the Page Builder to tell where the block has been dropped. + +Its data contains: +- the ID of the zone where the block has been dropped (`zoneId`) +- the ID of the block that is now next to the dropped block (`nextBlockId`) if the dropped block isn't the last one of the zone. + +In the following example, `targetBlockId` is the ID of a block the dropped block was dropped on or just before, so the dragged block takes its place and move it below, or `null` when dropped at the bottom of the zone. + +```js +const dropResponseMessage = { + type: 'APP:DROP_RESPONSE', + data: { + zoneId: zoneId, + nextBlockId: targetBlockId, + } +}; +``` + +TODO: `PB:SCROLL_BY` when a block is dragged near the top or bottom of the preview, and it needs to be scrolled up or down. From 00941501be36e2963899c538d6ce73923d1e1540 Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Fri, 18 Sep 2026 10:40:54 +0200 Subject: [PATCH 03/31] Continue documenting Headless Page Builder --- .../pages/headless_page_builder.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index f89c3a3d66b..6ecbca92a42 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -281,9 +281,9 @@ It has no data. Combined with the last `PB:DRAG_OVER` message, the front-end can Its data contains: - the ID of the zone where the block has been dropped (`zoneId`) -- the ID of the block that is now next to the dropped block (`nextBlockId`) if the dropped block isn't the last one of the zone. +- the ID of a block that is now below the dropped block (`nextBlockId`) if the dropped block isn't the last one of the zone. -In the following example, `targetBlockId` is the ID of a block the dropped block was dropped on or just before, so the dragged block takes its place and move it below, or `null` when dropped at the bottom of the zone. +In the following example, `targetBlockId` value is the ID of a block the dropped block was dropped on or just before, so the dragged block takes its place and move it below, or `null` when dropped at the bottom of the zone. ```js const dropResponseMessage = { @@ -295,4 +295,15 @@ const dropResponseMessage = { }; ``` -TODO: `PB:SCROLL_BY` when a block is dragged near the top or bottom of the preview, and it needs to be scrolled up or down. +`PB:SCROLL_BY` message is sent from the Page Builder when a block is dragged near a border of the preview which needs to be scrolled. +Its data contains the `top` or `left` amount to scroll by. + +```js +window.addEventListener('message', (messageEvent) => { + switch (messageEvent.data.type) { + case 'PB:SCROLL_BY': + window.scrollBy(messageEvent.data.data); + break; + } +}); +``` From 2e1165054539ba47114a17583fbb6b373866773b Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Fri, 18 Sep 2026 11:56:55 +0200 Subject: [PATCH 04/31] Continue documenting Headless Page Builder --- .../pages/headless_page_builder.md | 94 ++++++++++++++----- 1 file changed, 73 insertions(+), 21 deletions(-) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index 6ecbca92a42..8b1ec3b4f47 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -70,27 +70,27 @@ So the front-end can declare which capabilities it supports and the Page Builder The handshake and core messages are mandatory and not related to an optional capability. -| Capability | Message type | Description | -|------------------|----------------------------------------------------|-----------------------------------------------------------------------------------------------------------| -| (handshake) | [`APP:INITIALIZED`](#communication-initialization) | To establish the communication and declare which protocol version and capabilities are supported. | -| (handshake) | [`PB:INIT_MODE`](#communication-initialization) | To validate the communication and give information about the edited content draft. | -| (core) | [`PB:UPDATE_FIELD_DATA`](#on-field-update) | To notify that the field has changed, like when a block have been edited or the layout has been switched. | -| (core) | [`PB:DISPATCH_EVENT`](##re-dispatching-events) | TODO: To notify of event that should be dispached | -| blocks.dnd | [`PB:DRAG_START_PREVIEW`](#drag-and-drop) | To notify that an existing block starts being dragged in the preview. | -| blocks.dnd | [`PB:DRAG_OVER`](#drag-and-drop) | To give the position of the mouse while a block is dragged. | -| blocks.dnd | [`PB:DRAG_END_PREVIEW`](#drag-and-drop) | To notify that an existing block stopped being dragged in the preview. | -| blocks.dnd | [`PB:DROP`](#drag-and-drop) | To notify that a block has been dropped. | -| blocks.dnd | [`APP:DROP_RESPONSE`](#drag-and-drop) | To notify that the drop action has been processed and declare which zone welcomed the block. | -| blocks.dnd | [`PB:SCROLL_BY`](#drag-and-drop) | TODO | -| blocks.geometry | APP:POSITIONS_UPDATE | To declare the actual position of the blocks (so the block editing menus can be positionned). | -| blocks.geometry | APP:SCROLL_END | TODO | -| blocks.remove | PB:BLOCK_REMOVE | TODO | -| blocks.remove | APP:BLOCK_REMOVE_RESPONSE | TODO | -| blocks.remove | APP:BLOCK_REMOVE_REQUEST | TODO | -| blocks.reveal | PB:SCROLL_INTO_BLOCK | TODO | -| blocks.select | APP:BLOCK_CLICKED | To notify that a block has been clicked. | -| pointer.tracking | APP:MOUSE_POSITION | To declare the actual position of the mouse (so the block editing menus can be displayed on hover). | -| preview.params | PB:UPDATE_PREVIEW_PARAMS | TODO | +| Capability | Message type | Description | +|------------------|---------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------| +| (handshake) | [`APP:INITIALIZED`](#communication-initialization) | To establish the communication and declare which protocol version and capabilities are supported. | +| (handshake) | [`PB:INIT_MODE`](#communication-initialization) | To validate the communication and give information about the edited content draft. | +| (core) | [`PB:UPDATE_FIELD_DATA`](#on-field-update) | To notify that the field has changed, like when a block have been edited or the layout has been switched. | +| (core) | [`PB:DISPATCH_EVENT`](#re-dispatching-events) | TODO: To notify of event that should be dispached | +| blocks.dnd | [`PB:DRAG_START_PREVIEW`](#drag-and-drop-blocksdnd) | To notify that an existing block starts being dragged in the preview. | +| blocks.dnd | [`PB:DRAG_OVER`](#drag-and-drop-blocksdnd) | To give the position of the mouse while a block is dragged. | +| blocks.dnd | [`PB:DRAG_END_PREVIEW`](#drag-and-drop-blocksdnd) | To notify that an existing block stopped being dragged in the preview. | +| blocks.dnd | [`PB:DROP`](#drag-and-drop-blocksdnd) | To notify that a block has been dropped. | +| blocks.dnd | [`APP:DROP_RESPONSE`](#drag-and-drop-blocksdnd) | To notify that the drop action has been processed and declare which zone welcomed the block. | +| blocks.dnd | [`PB:SCROLL_BY`](#drag-and-drop-blocksdnd) | TODO | +| blocks.geometry | [`APP:POSITIONS_UPDATE`](#geometry-and-pointer-tracking-blocksgeometry-and-pointertracking) | To declare the actual position of the blocks (so the block editing menus can be positionned). | +| blocks.geometry | [`APP:SCROLL_END`](#geometry-and-pointer-tracking-blocksgeometry-and-pointertracking) | TODO | +| blocks.remove | PB:BLOCK_REMOVE | TODO | +| blocks.remove | APP:BLOCK_REMOVE_RESPONSE | TODO | +| blocks.remove | APP:BLOCK_REMOVE_REQUEST | TODO | +| blocks.reveal | PB:SCROLL_INTO_BLOCK | TODO | +| blocks.select | APP:BLOCK_CLICKED | To notify that a block has been clicked. | +| pointer.tracking | [`APP:MOUSE_POSITION`](#geometry-and-pointer-tracking-blocksgeometry-and-pointertracking) | To declare the actual position of the mouse (so the block editing menus can be displayed on hover). | +| preview.params | PB:UPDATE_PREVIEW_PARAMS | TODO | ### Communication initialization @@ -267,10 +267,62 @@ TODO: Available events - `ibexa-active-block-clicked`? - `ibexa-post-update-blocks-preview`? +### Geometry and pointer tracking (`blocks.geometry` and `pointer.tracking`) + +The pointer tracking and the geometry helps the Page Builder to position the block editing menus above the front-end preview. +Such menu is a `.c-pb-headless-preview-menu` element positioned by the Page Builder from its DOM above the preview `iframe`. + +`APP:MOUSE_POSITION` message is sent from the front-end preview to the Page Builder to declare the actual position of the mouse. + +```js +window.addEventListener('mousemove', (mouseEvent) => { + window.parent.postMessage({ + type: 'APP:MOUSE_POSITION', + data: { + x: mouseEvent.clientX, + y: mouseEvent.clientY, + }, + }, pbOrigin); +}); +``` + +`APP:POSITIONS_UPDATE` message is sent from the front-end preview to the Page Builder to declare the actual position of the blocks. + +```js +const positionsUpdate = () => { + let blocks = []; + for (const blockElement of document.getElementsByClassName('landing-page__block')) { + const blockId = blockElement.dataset.ibexaBlockId; + const blockRect = blockElement.getBoundingClientRect(); + blocks.push({ + id: blockId, + top: blockRect.top, + left: blockRect.left, + right: blockRect.right, + bottom: blockRect.bottom, + width: blockRect.width, + height: blockRect.height, + }); + } + window.parent.postMessage({ + type: 'APP:POSITIONS_UPDATE', + data: { + blocks: blocks, + }, + }, pbOrigin); +}; +``` + +TODO: `APP:SCROLL_END` message is sent from the front-end preview to the Page Builder to notify that a scroll operation has ended. + ### Drag and drop (`blocks.dnd`) `PB:DRAG_OVER` message is sent from the Page Builder to the front-end preview to give the position of the mouse while a (new or existing) block is dragged. +!!! tip +- `APP:MOUSE_POSITION` helps the Page Builder to know where the mouse is when moved over the preview. +- `PB:DRAG_OVER` helps the front-end to know where the mouse is when a block is dragged over the preview. + `PB:DRAG_START_PREVIEW` and `PB:DRAG_END_PREVIEW` are sent at the beginning and at the end of a drag operation on an existing block in the front-end preview. Its data contains the ID of the block being dragged (`blockId`). From a4e73a7abe7a86c2eae69d0c33c454daedc8d3d2 Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Fri, 18 Sep 2026 12:37:17 +0200 Subject: [PATCH 05/31] headless_page_builder.md: Fix MD032/blanks-around-lists --- docs/content_management/pages/headless_page_builder.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index 8b1ec3b4f47..8dc0a515cb4 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -118,6 +118,7 @@ The Page Builder replies with a confirmation message. The initialization message might be sent several times until the Page Builder replies to it. This confirmation `data` contains: + - the actual version of the protocol used (`protocol.version`) and the other supported versions (`protocol.supported`) - a list of all available capabilities (`capabilities`) - a list of the existing block types, their attributes, and their configuration (`blocksConfig`) @@ -229,6 +230,7 @@ This confirmation `data` contains: The `PB:UPDATE_FIELD_DATA` message is sent from the Page Builder to the front-end resource when the Landing page field value is updated. Its data contains the new value of the field with the following structure: + - a list of the existing block types, their attributes, and their configuration (`blocksConfig`) - the current value of the Landing page field being edited (`fieldValue`) including the layout, zones, and blocks. - a block-ID-to-name mapping (`blocksIdMap`) @@ -264,6 +266,7 @@ window.addEventListener('message', (messageEvent) => { ``` TODO: Available events + - `ibexa-active-block-clicked`? - `ibexa-post-update-blocks-preview`? @@ -320,8 +323,9 @@ TODO: `APP:SCROLL_END` message is sent from the front-end preview to the Page Bu `PB:DRAG_OVER` message is sent from the Page Builder to the front-end preview to give the position of the mouse while a (new or existing) block is dragged. !!! tip -- `APP:MOUSE_POSITION` helps the Page Builder to know where the mouse is when moved over the preview. -- `PB:DRAG_OVER` helps the front-end to know where the mouse is when a block is dragged over the preview. + + - `APP:MOUSE_POSITION` helps the Page Builder to know where the mouse is when moved over the preview. + - `PB:DRAG_OVER` helps the front-end to know where the mouse is when a block is dragged over the preview. `PB:DRAG_START_PREVIEW` and `PB:DRAG_END_PREVIEW` are sent at the beginning and at the end of a drag operation on an existing block in the front-end preview. Its data contains the ID of the block being dragged (`blockId`). @@ -332,6 +336,7 @@ It has no data. Combined with the last `PB:DRAG_OVER` message, the front-end can `APP:DROP_RESPONSE` message is sent from the front-end preview to the Page Builder to tell where the block has been dropped. Its data contains: + - the ID of the zone where the block has been dropped (`zoneId`) - the ID of a block that is now below the dropped block (`nextBlockId`) if the dropped block isn't the last one of the zone. From 7c282d7f5b4907c57639ee109dd352aa18523de7 Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Fri, 18 Sep 2026 16:38:33 +0200 Subject: [PATCH 06/31] Continue documenting Headless Page Builder --- .../pages/headless_page_builder.md | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index 8dc0a515cb4..8caeb1e91fe 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -290,6 +290,8 @@ window.addEventListener('mousemove', (mouseEvent) => { ``` `APP:POSITIONS_UPDATE` message is sent from the front-end preview to the Page Builder to declare the actual position of the blocks. +Its data contains a list of objects with block IDs, their positions, and dimensions in the front-end preview. +This format is close to [`getBoundingClientRect()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect) method. ```js const positionsUpdate = () => { @@ -316,7 +318,32 @@ const positionsUpdate = () => { }; ``` -TODO: `APP:SCROLL_END` message is sent from the front-end preview to the Page Builder to notify that a scroll operation has ended. +This message should be sent each time the positions of the blocks change. +It should be sent after updating the blocks, like in response to [`PB:UPDATE_FIELD_DATA`](#on-field-update). +It should be sent after scrolling or resizing. + +`APP:SCROLL_END` message is sent from the front-end preview to the Page Builder to notify that a scroll operation has ended. +It has no data. + +```js +window.addEventListener('scrollend', (event) => { + window.parent.postMessage({ + type: 'APP:SCROLL_END', + }, pbOrigin); + positionsUpdate(); +}); +window.addEventListener('resize', (event) => { + positionsUpdate(); +}); +window.addEventListener('message', (messageEvent) => { + switch (messageEvent.data.type) { + case 'PB:UPDATE_FIELD_DATA': + renderZones(messageEvent.data.data.fieldValue.zones); + positionsUpdate(); + break; + } +}); +``` ### Drag and drop (`blocks.dnd`) From 975b6ae056ef13f598e2dce413fd2e311ba5691a Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Fri, 18 Sep 2026 16:58:34 +0200 Subject: [PATCH 07/31] More TODOs about Headless Page Builder --- docs/content_management/pages/headless_page_builder.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index 8caeb1e91fe..df480e4e8ac 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -345,6 +345,8 @@ window.addEventListener('message', (messageEvent) => { }); ``` +TODO: Is there other events that should trigger a positions update? + ### Drag and drop (`blocks.dnd`) `PB:DRAG_OVER` message is sent from the Page Builder to the front-end preview to give the position of the mouse while a (new or existing) block is dragged. @@ -391,3 +393,5 @@ window.addEventListener('message', (messageEvent) => { } }); ``` + +TODO: See `APP:SCROLL_END` message to declare the end of the scroll operation and trigger a `APP:POSITIONS_UPDATE` message to update the blocks positions. From 2980d36035270a330ec9fff6f74a466dd805d347 Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Fri, 18 Sep 2026 17:46:31 +0200 Subject: [PATCH 08/31] Continue documenting Headless Page Builder --- .../pages/headless_page_builder.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index df480e4e8ac..7acc89e8e5e 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -395,3 +395,16 @@ window.addEventListener('message', (messageEvent) => { ``` TODO: See `APP:SCROLL_END` message to declare the end of the scroll operation and trigger a `APP:POSITIONS_UPDATE` message to update the blocks positions. + +### Block removal (`blocks.remove`) + +`PB:BLOCK_REMOVE` message is sent from the Page Builder to the front-end preview to notify that a block should be removed, for example, from the Structure view. +Its data contains the ID of the block to remove (`blockId`). + +`APP:BLOCK_REMOVE_RESPONSE` message is sent from the front-end preview to the Page Builder to confirm that the block has been removed as requested by `PB:BLOCK_REMOVE`. +Its data contains the ID of the removed block (`blockId`). +It can be sent immediately or after removal animation. + +`APP:BLOCK_REMOVE_REQUEST` message is sent from the front-end preview to the Page Builder to request the removal of a block. +Its data contains the ID of the block to remove (`blockId`). +The Page Builder responses with a `PB:UPDATE_FIELD_DATA`. From 2c6ecae8ea914f7a82913ccb13632f9ad7a0be17 Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Fri, 18 Sep 2026 18:10:14 +0200 Subject: [PATCH 09/31] Continue documenting Headless Page Builder --- .../pages/headless_page_builder.md | 62 ++++++++++++------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index 7acc89e8e5e..4d7fb49a77d 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -70,27 +70,27 @@ So the front-end can declare which capabilities it supports and the Page Builder The handshake and core messages are mandatory and not related to an optional capability. -| Capability | Message type | Description | -|------------------|---------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------| -| (handshake) | [`APP:INITIALIZED`](#communication-initialization) | To establish the communication and declare which protocol version and capabilities are supported. | -| (handshake) | [`PB:INIT_MODE`](#communication-initialization) | To validate the communication and give information about the edited content draft. | -| (core) | [`PB:UPDATE_FIELD_DATA`](#on-field-update) | To notify that the field has changed, like when a block have been edited or the layout has been switched. | -| (core) | [`PB:DISPATCH_EVENT`](#re-dispatching-events) | TODO: To notify of event that should be dispached | -| blocks.dnd | [`PB:DRAG_START_PREVIEW`](#drag-and-drop-blocksdnd) | To notify that an existing block starts being dragged in the preview. | -| blocks.dnd | [`PB:DRAG_OVER`](#drag-and-drop-blocksdnd) | To give the position of the mouse while a block is dragged. | -| blocks.dnd | [`PB:DRAG_END_PREVIEW`](#drag-and-drop-blocksdnd) | To notify that an existing block stopped being dragged in the preview. | -| blocks.dnd | [`PB:DROP`](#drag-and-drop-blocksdnd) | To notify that a block has been dropped. | -| blocks.dnd | [`APP:DROP_RESPONSE`](#drag-and-drop-blocksdnd) | To notify that the drop action has been processed and declare which zone welcomed the block. | -| blocks.dnd | [`PB:SCROLL_BY`](#drag-and-drop-blocksdnd) | TODO | -| blocks.geometry | [`APP:POSITIONS_UPDATE`](#geometry-and-pointer-tracking-blocksgeometry-and-pointertracking) | To declare the actual position of the blocks (so the block editing menus can be positionned). | -| blocks.geometry | [`APP:SCROLL_END`](#geometry-and-pointer-tracking-blocksgeometry-and-pointertracking) | TODO | -| blocks.remove | PB:BLOCK_REMOVE | TODO | -| blocks.remove | APP:BLOCK_REMOVE_RESPONSE | TODO | -| blocks.remove | APP:BLOCK_REMOVE_REQUEST | TODO | -| blocks.reveal | PB:SCROLL_INTO_BLOCK | TODO | -| blocks.select | APP:BLOCK_CLICKED | To notify that a block has been clicked. | -| pointer.tracking | [`APP:MOUSE_POSITION`](#geometry-and-pointer-tracking-blocksgeometry-and-pointertracking) | To declare the actual position of the mouse (so the block editing menus can be displayed on hover). | -| preview.params | PB:UPDATE_PREVIEW_PARAMS | TODO | +| Capability | Message type | Description | +|--------------------|---------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------| +| (handshake) | [`APP:INITIALIZED`](#communication-initialization) | To establish the communication and declare which protocol version and capabilities are supported. | +| (handshake) | [`PB:INIT_MODE`](#communication-initialization) | To validate the communication and give information about the edited content draft. | +| (core) | [`PB:UPDATE_FIELD_DATA`](#on-field-update) | To notify that the field has changed, like when a block have been edited or the layout has been switched. | +| (core) | [`PB:DISPATCH_EVENT`](#re-dispatching-events) | To notify of event that should be dispached in front-end preview. | +| `blocks.dnd` | [`PB:DRAG_START_PREVIEW`](#drag-and-drop-blocksdnd) | To notify that an existing block starts being dragged in the preview. | +| `blocks.dnd` | [`PB:DRAG_OVER`](#drag-and-drop-blocksdnd) | To give the position of the mouse while a block is dragged. | +| `blocks.dnd` | [`PB:DRAG_END_PREVIEW`](#drag-and-drop-blocksdnd) | To notify that an existing block stopped being dragged in the preview. | +| `blocks.dnd` | [`PB:DROP`](#drag-and-drop-blocksdnd) | To notify that a block has been dropped. | +| `blocks.dnd` | [`APP:DROP_RESPONSE`](#drag-and-drop-blocksdnd) | To notify that the drop action has been processed and declare which zone welcomed the block. | +| `blocks.dnd` | [`PB:SCROLL_BY`](#drag-and-drop-blocksdnd) | To notify that the preview should be scrolled. | +| `blocks.geometry` | [`APP:POSITIONS_UPDATE`](#geometry-and-pointer-tracking-blocksgeometry-and-pointertracking) | To declare the actual position of the blocks (so the block editing menus can be positionned). | +| `blocks.geometry` | [`APP:SCROLL_END`](#geometry-and-pointer-tracking-blocksgeometry-and-pointertracking) | To notify that the preview stopped scrolling. | +| `blocks.remove` | [`PB:BLOCK_REMOVE`](#block-removal-blocksremove) | To notify the preview that a block is removed. | +| `blocks.remove` | [`APP:BLOCK_REMOVE_RESPONSE`](#block-removal-blocksremove) | To the the Page Builder that the block has been removed. | +| `blocks.remove` | [`APP:BLOCK_REMOVE_REQUEST`](#block-removal-blocksremove) | To ask the Page Builder to remove a block. | +| `blocks.reveal` | [`PB:SCROLL_INTO_BLOCK`](#block-reveal-blocksreveal) | To notify the preview to scroll to have a specific block into view. | +| `blocks.select` | `APP:BLOCK_CLICKED` | TODO: To notify that a block has been clicked. | +| `pointer.tracking` | [`APP:MOUSE_POSITION`](#geometry-and-pointer-tracking-blocksgeometry-and-pointertracking) | To declare the actual position of the mouse (so the block editing menus can be displayed on hover). | +| `preview.params` | `PB:UPDATE_PREVIEW_PARAMS` | TODO | ### Communication initialization @@ -394,7 +394,25 @@ window.addEventListener('message', (messageEvent) => { }); ``` -TODO: See `APP:SCROLL_END` message to declare the end of the scroll operation and trigger a `APP:POSITIONS_UPDATE` message to update the blocks positions. +See [Geometry (`blocks.geometry`)](#geometry-and-pointer-tracking-blocksgeometry-and-pointertracking)'s `APP:SCROLL_END` message to declare the end of the scroll operation +and `APP:POSITIONS_UPDATE` message to update the blocks positions. + +### Block reveal (`blocks.reveal`) + +`PB:SCROLL_INTO_BLOCK` is send by the Page Builder to the front-end preview to request that a block is scrolled into view. +Its data contains the ID of the block to scroll into view (`blockId`). +It can be used with the [`scrollIntoView()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView) method. + +```js +window.addEventListener('message', (messageEvent) => { + switch (messageEvent.data.type) { + case 'PB:SCROLL_INTO_BLOCK': + const blockElementToScrollInto = document.getElementById('block_' + messageEvent.data.data.blockId); + blockElementToScrollInto.scrollIntoView({ behavior: 'smooth', block: 'center' }); + break; + } +}); +``` ### Block removal (`blocks.remove`) From a66a830b841420305b6a8cc6385bd4204edb00fa Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Fri, 18 Sep 2026 18:12:36 +0200 Subject: [PATCH 10/31] Continue documenting Headless Page Builder --- docs/content_management/pages/headless_page_builder.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index 4d7fb49a77d..b004721f115 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -85,7 +85,7 @@ The handshake and core messages are mandatory and not related to an optional cap | `blocks.geometry` | [`APP:POSITIONS_UPDATE`](#geometry-and-pointer-tracking-blocksgeometry-and-pointertracking) | To declare the actual position of the blocks (so the block editing menus can be positionned). | | `blocks.geometry` | [`APP:SCROLL_END`](#geometry-and-pointer-tracking-blocksgeometry-and-pointertracking) | To notify that the preview stopped scrolling. | | `blocks.remove` | [`PB:BLOCK_REMOVE`](#block-removal-blocksremove) | To notify the preview that a block is removed. | -| `blocks.remove` | [`APP:BLOCK_REMOVE_RESPONSE`](#block-removal-blocksremove) | To the the Page Builder that the block has been removed. | +| `blocks.remove` | [`APP:BLOCK_REMOVE_RESPONSE`](#block-removal-blocksremove) | To tell the Page Builder that the block has been removed. | | `blocks.remove` | [`APP:BLOCK_REMOVE_REQUEST`](#block-removal-blocksremove) | To ask the Page Builder to remove a block. | | `blocks.reveal` | [`PB:SCROLL_INTO_BLOCK`](#block-reveal-blocksreveal) | To notify the preview to scroll to have a specific block into view. | | `blocks.select` | `APP:BLOCK_CLICKED` | TODO: To notify that a block has been clicked. | From e8814cb248bb8d6a3e60a7a75f7166ff1ef0a584 Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Fri, 18 Sep 2026 18:16:00 +0200 Subject: [PATCH 11/31] Shorten message type Description column w/ Copilot --- .../pages/headless_page_builder.md | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index b004721f115..c9f71253de2 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -70,27 +70,27 @@ So the front-end can declare which capabilities it supports and the Page Builder The handshake and core messages are mandatory and not related to an optional capability. -| Capability | Message type | Description | -|--------------------|---------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------| -| (handshake) | [`APP:INITIALIZED`](#communication-initialization) | To establish the communication and declare which protocol version and capabilities are supported. | -| (handshake) | [`PB:INIT_MODE`](#communication-initialization) | To validate the communication and give information about the edited content draft. | -| (core) | [`PB:UPDATE_FIELD_DATA`](#on-field-update) | To notify that the field has changed, like when a block have been edited or the layout has been switched. | -| (core) | [`PB:DISPATCH_EVENT`](#re-dispatching-events) | To notify of event that should be dispached in front-end preview. | -| `blocks.dnd` | [`PB:DRAG_START_PREVIEW`](#drag-and-drop-blocksdnd) | To notify that an existing block starts being dragged in the preview. | -| `blocks.dnd` | [`PB:DRAG_OVER`](#drag-and-drop-blocksdnd) | To give the position of the mouse while a block is dragged. | -| `blocks.dnd` | [`PB:DRAG_END_PREVIEW`](#drag-and-drop-blocksdnd) | To notify that an existing block stopped being dragged in the preview. | -| `blocks.dnd` | [`PB:DROP`](#drag-and-drop-blocksdnd) | To notify that a block has been dropped. | -| `blocks.dnd` | [`APP:DROP_RESPONSE`](#drag-and-drop-blocksdnd) | To notify that the drop action has been processed and declare which zone welcomed the block. | -| `blocks.dnd` | [`PB:SCROLL_BY`](#drag-and-drop-blocksdnd) | To notify that the preview should be scrolled. | -| `blocks.geometry` | [`APP:POSITIONS_UPDATE`](#geometry-and-pointer-tracking-blocksgeometry-and-pointertracking) | To declare the actual position of the blocks (so the block editing menus can be positionned). | -| `blocks.geometry` | [`APP:SCROLL_END`](#geometry-and-pointer-tracking-blocksgeometry-and-pointertracking) | To notify that the preview stopped scrolling. | -| `blocks.remove` | [`PB:BLOCK_REMOVE`](#block-removal-blocksremove) | To notify the preview that a block is removed. | -| `blocks.remove` | [`APP:BLOCK_REMOVE_RESPONSE`](#block-removal-blocksremove) | To tell the Page Builder that the block has been removed. | -| `blocks.remove` | [`APP:BLOCK_REMOVE_REQUEST`](#block-removal-blocksremove) | To ask the Page Builder to remove a block. | -| `blocks.reveal` | [`PB:SCROLL_INTO_BLOCK`](#block-reveal-blocksreveal) | To notify the preview to scroll to have a specific block into view. | -| `blocks.select` | `APP:BLOCK_CLICKED` | TODO: To notify that a block has been clicked. | -| `pointer.tracking` | [`APP:MOUSE_POSITION`](#geometry-and-pointer-tracking-blocksgeometry-and-pointertracking) | To declare the actual position of the mouse (so the block editing menus can be displayed on hover). | -| `preview.params` | `PB:UPDATE_PREVIEW_PARAMS` | TODO | +| Capability | Message type | Description | +|--------------------|---------------------------------------------------------------------------------------------|--------------------------------------| +| (handshake) | [`APP:INITIALIZED`](#communication-initialization) | Establish protocol and capabilities. | +| (handshake) | [`PB:INIT_MODE`](#communication-initialization) | Confirm protocol and draft info. | +| (core) | [`PB:UPDATE_FIELD_DATA`](#on-field-update) | Send updated field data. | +| (core) | [`PB:DISPATCH_EVENT`](#re-dispatching-events) | Re-dispatch a front-end event. | +| `blocks.dnd` | [`PB:DRAG_START_PREVIEW`](#drag-and-drop-blocksdnd) | Existing block drag started. | +| `blocks.dnd` | [`PB:DRAG_OVER`](#drag-and-drop-blocksdnd) | Mouse position during drag. | +| `blocks.dnd` | [`PB:DRAG_END_PREVIEW`](#drag-and-drop-blocksdnd) | Existing block drag ended. | +| `blocks.dnd` | [`PB:DROP`](#drag-and-drop-blocksdnd) | Drop notification. | +| `blocks.dnd` | [`APP:DROP_RESPONSE`](#drag-and-drop-blocksdnd) | Report where the block was dropped. | +| `blocks.dnd` | [`PB:SCROLL_BY`](#drag-and-drop-blocksdnd) | Scroll the preview. | +| `blocks.geometry` | [`APP:POSITIONS_UPDATE`](#geometry-and-pointer-tracking-blocksgeometry-and-pointertracking) | Report block positions. | +| `blocks.geometry` | [`APP:SCROLL_END`](#geometry-and-pointer-tracking-blocksgeometry-and-pointertracking) | Scroll ended. | +| `blocks.remove` | [`PB:BLOCK_REMOVE`](#block-removal-blocksremove) | Remove a block. | +| `blocks.remove` | [`APP:BLOCK_REMOVE_RESPONSE`](#block-removal-blocksremove) | Confirm removal. | +| `blocks.remove` | [`APP:BLOCK_REMOVE_REQUEST`](#block-removal-blocksremove) | Request block removal. | +| `blocks.reveal` | [`PB:SCROLL_INTO_BLOCK`](#block-reveal-blocksreveal) | Scroll a block into view. | +| `blocks.select` | `APP:BLOCK_CLICKED` | TODO: Block clicked. | +| `pointer.tracking` | [`APP:MOUSE_POSITION`](#geometry-and-pointer-tracking-blocksgeometry-and-pointertracking) | Report mouse position. | +| `preview.params` | `PB:UPDATE_PREVIEW_PARAMS` | TODO: Update preview params. | ### Communication initialization From c3dc7d926ac122d0cdf8ddb02c2d1c1427328cdb Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Tue, 22 Sep 2026 12:24:36 +0200 Subject: [PATCH 12/31] Continue documenting Headless Page Builder --- .../pages/headless_page_builder.md | 75 ++++++++++++++++--- 1 file changed, 64 insertions(+), 11 deletions(-) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index c9f71253de2..76a161f64e7 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -90,7 +90,7 @@ The handshake and core messages are mandatory and not related to an optional cap | `blocks.reveal` | [`PB:SCROLL_INTO_BLOCK`](#block-reveal-blocksreveal) | Scroll a block into view. | | `blocks.select` | `APP:BLOCK_CLICKED` | TODO: Block clicked. | | `pointer.tracking` | [`APP:MOUSE_POSITION`](#geometry-and-pointer-tracking-blocksgeometry-and-pointertracking) | Report mouse position. | -| `preview.params` | `PB:UPDATE_PREVIEW_PARAMS` | TODO: Update preview params. | +| `preview.params` | [`PB:UPDATE_PREVIEW_PARAMS`](#preview-parameters-update-previewparams) | TODO: Update preview params. | ### Communication initialization @@ -106,7 +106,6 @@ const initializedMessage = { capabilities: [ 'blocks.dnd', 'blocks.geometry', - 'blocks.select', 'pointer.tracking', // … ], @@ -231,20 +230,21 @@ The `PB:UPDATE_FIELD_DATA` message is sent from the Page Builder to the front-en Its data contains the new value of the field with the following structure: -- a list of the existing block types, their attributes, and their configuration (`blocksConfig`) -- the current value of the Landing page field being edited (`fieldValue`) including the layout, zones, and blocks. -- a block-ID-to-name mapping (`blocksIdMap`) -- a list of Ids from the new blocks that have been added (`highlightedBlockIds`) +- Always, the current value of the Landing page field being edited (`fieldValue`) including the layout, zones, and blocks. +
For example, only `fieldValue` is sent when manipulating the [timeline]([[= user_doc =]]/content_management/schedule_publishing/#timeline)![](page_builder_toolbartimelinetoggler.png){style="display:inline;width:27px;vertical-align:middle;"}. +- Optionally, a list of the existing block types, their attributes, and their configuration (`blocksConfig`) +- Optionally, a block-ID-to-name mapping (`blocksIdMap`) +- Optionally, a list of Ids from the new blocks that have been added (`highlightedBlockIds`) ```json { "type": "PB:UPDATE_FIELD_DATA", "data": { - "blocksConfig": [], "fieldValue": { "layout": "…", "zones": [] }, + "blocksConfig": [], "blocksIdMap": {}, "highlightedBlockIds": [] } @@ -254,21 +254,32 @@ Its data contains the new value of the field with the following structure: ### Re-dispatching events The `PB:DISPATCH_EVENT` message is sent from the Page Builder to the front-end resource for being re-dispatched there as a custom event. +Its data contains the name of the event to dispatch (`eventName`) and the data to pass to the event detail (`eventData`). ```js window.addEventListener('message', (messageEvent) => { switch (messageEvent.data.type) { case 'PB:DISPATCH_EVENT': - document.body.dispatchEvent(new CustomEvent(messageEvent.data.data.eventName, { detail: messageEvent.data.data.eventDetail })); + window.dispatchEvent(new CustomEvent(messageEvent.data.data.eventName, { detail: messageEvent.data.data.eventData })); break; } }); ``` -TODO: Available events +#### Available events + +- `ibexa-active-block-clicked`: It confirms `APP:BLOCK_CLICKED` have been received. It has no data. +- `ibexa-post-update-blocks-preview`: It's a complement to [`PB:UPDATE_FIELD_DATA`](#on-field-update) with more data + - `fieldValue`: The same as in `PB:UPDATE_FIELD_DATA` + - `blockIds`: A list of all the block IDs + - `blocksMaps`: A map of block config per block ID -- `ibexa-active-block-clicked`? -- `ibexa-post-update-blocks-preview`? +```js +window.addEventListener('ibexa-post-update-blocks-preview', (customEvent) => { + setLayout(customEvent.details.fieldValue.layout); + renderZones(customEvent.details.fieldValue.zones); +}); +``` ### Geometry and pointer tracking (`blocks.geometry` and `pointer.tracking`) @@ -338,6 +349,7 @@ window.addEventListener('resize', (event) => { window.addEventListener('message', (messageEvent) => { switch (messageEvent.data.type) { case 'PB:UPDATE_FIELD_DATA': + setLayout(messageEvent.data.data.fieldValue.layout); renderZones(messageEvent.data.data.fieldValue.zones); positionsUpdate(); break; @@ -423,6 +435,47 @@ Its data contains the ID of the block to remove (`blockId`). Its data contains the ID of the removed block (`blockId`). It can be sent immediately or after removal animation. +```js +window.addEventListener('message', (messageEvent) => { + switch (messageEvent.data.type) { + case 'PB:BLOCK_REMOVE': + const blockId = messageEvent.data.data.blockId; + const blockElementToRemove = document.getElementById('block_' + blockId); + if (blockElementToRemove) { + blockElementToRemove.addEventListener('animationend', () => { + blockElementToRemove.remove(); + window.parent.postMessage({ + type: 'APP:BLOCK_REMOVE_RESPONSE', + data: { + blockId: blockId, + }, + }); + }); + blockElementToRemove.classList.add('c-pb-block-preview--is-removing'); + } else { + console.error('No block element found for block ID ' + messageEvent.data.data.blockId, 'notification.headless_unresponsive_preview'); + } + break; + } +}); +``` +```css +.c-pb-block-preview--is-removing { + animation-duration: 1s; + animation-name: c-pb-block-preview--is-removing; +} +@keyframes c-pb-block-preview--is-removing { + to { + opacity: 0; + height: 0; + } +} +``` + `APP:BLOCK_REMOVE_REQUEST` message is sent from the front-end preview to the Page Builder to request the removal of a block. Its data contains the ID of the block to remove (`blockId`). The Page Builder responses with a `PB:UPDATE_FIELD_DATA`. + +### Preview parameters update (`preview.params`) + +`PB:UPDATE_PREVIEW_PARAMS` message is sent from the Page Builder to the front-end preview when TODO: it's sent on several occasions without data. It seems also (if not mainly) used by segmentation. From ab7abbc7a1ad1ff8c196994f95b0eae7ea93f002 Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Wed, 23 Sep 2026 16:08:42 +0200 Subject: [PATCH 13/31] Continue documenting Headless Page Builder --- .../img/headless-page-field-edit.png | Bin 0 -> 47199 bytes .../img/headless-saas-siteaccess-config.png | Bin 0 -> 66430 bytes .../img/page-edit-headless.png | Bin 46644 -> 0 bytes .../pages/headless_page_builder.md | 25 ++++++++++++++---- 4 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 docs/content_management/img/headless-page-field-edit.png create mode 100644 docs/content_management/img/headless-saas-siteaccess-config.png delete mode 100644 docs/content_management/img/page-edit-headless.png diff --git a/docs/content_management/img/headless-page-field-edit.png b/docs/content_management/img/headless-page-field-edit.png new file mode 100644 index 0000000000000000000000000000000000000000..377d3be0995f24668ebcbdf0171d634a56217d8f GIT binary patch literal 47199 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 I_j*463lNexng9R* literal 0 HcmV?d00001 diff --git a/docs/content_management/img/headless-saas-siteaccess-config.png b/docs/content_management/img/headless-saas-siteaccess-config.png new file mode 100644 index 0000000000000000000000000000000000000000..8ed5009f4c1c5bf40b49303aaea74a0c467e7a9f GIT binary patch literal 66430 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 D3;k1O literal 0 HcmV?d00001 diff --git a/docs/content_management/img/page-edit-headless.png b/docs/content_management/img/page-edit-headless.png deleted file mode 100644 index ebd239930c0501c081d20ff753e355eacc2d787b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46644 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 D)kYs% diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index 76a161f64e7..e0644b4a85b 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -12,7 +12,9 @@ You provide a single URL for the front-end page and let it communicate with the The usage of this front-end page instead of the DXP one is set per content type. TODO: This is on-prem only, SaaS don't have the choice -## Configuration TODO: How this is declared on Saas? +## Configuration (on-prem) + +TODO: on-premise only, remove from SaaS documentation First, set up the feature, for example, in `config/packages/ibexa_page_builder.yaml`: @@ -23,13 +25,26 @@ ibexa: page_builder: headless: enabled: true - base_url: 'https://example.com/page.html' # The front-end URL loaded by the Page Builder's iframe + base_url: 'https://frontend.example.com/page-builder-preview' # The front-end URL loaded by the Page Builder's iframe + TODO: preview_url ``` Then, edit the content types with Landing page field type that are used headless, edit that field, and check the option "Edit in the headless Page Builder". -![Checked "Edit in the headless Page Builder"](page-edit-headless.png) +![Checked "Edit in the headless Page Builder"](headless-page-field-edit.png) + +## Configuration (SaaS) + +TODO: Saas only, remove from on-premise documentation + +Navigate to **Administration** > **SiteAccess Configuration** > **Headless** (`/siteaccess-config/default/headless`) + +TODO: Should `admin` SiteAccess be picked instead of staying on `default`? (`/siteaccess-config/admin/headless`) + +Below the description, enable the **Headless mode**, fill in the **Page Builder preview URL**, and **Save** the configuration. + +![Headless mode enabled with Page Builder preview URL](headless-saas-siteaccess-config.png) ## Communication protocol @@ -269,8 +284,8 @@ window.addEventListener('message', (messageEvent) => { #### Available events - `ibexa-active-block-clicked`: It confirms `APP:BLOCK_CLICKED` have been received. It has no data. -- `ibexa-post-update-blocks-preview`: It's a complement to [`PB:UPDATE_FIELD_DATA`](#on-field-update) with more data - - `fieldValue`: The same as in `PB:UPDATE_FIELD_DATA` +- `ibexa-post-update-blocks-preview`: It's sent when the timeline is used. + - `fieldValue`: The same as in [`PB:UPDATE_FIELD_DATA`](#on-field-update) TODO: Why when timeline move to a revelation time, the block is still invisible here while made visible in PB:UPDATE_FIELD_DATA? - `blockIds`: A list of all the block IDs - `blocksMaps`: A map of block config per block ID From 9b329de1e5154dfcb5c65d5f11342291ef4f910e Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Wed, 23 Sep 2026 16:14:15 +0200 Subject: [PATCH 14/31] Continue documenting Headless Page Builder --- docs/content_management/pages/headless_page_builder.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index e0644b4a85b..4902fec9714 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -22,11 +22,10 @@ First, set up the feature, for example, in `config/packages/ibexa_page_builder.y ibexa: system: admin_group: - page_builder: - headless: - enabled: true - base_url: 'https://frontend.example.com/page-builder-preview' # The front-end URL loaded by the Page Builder's iframe - TODO: preview_url + headless: + enabled: true + page_builder: + preview_url: 'https://frontend.example.com/page-builder-preview' # The front-end URL loaded by the Page Builder's iframe ``` Then, edit the content types with Landing page field type that are used headless, From cc69944182934fb9a50158b7f75aaeb87c256f11 Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Fri, 25 Sep 2026 09:43:48 +0200 Subject: [PATCH 15/31] Continue documenting Headless Page Builder --- .../pages/headless_page_builder.md | 68 +++++++++++++++++-- 1 file changed, 63 insertions(+), 5 deletions(-) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index 4902fec9714..564b0e964c3 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -134,7 +134,7 @@ This confirmation `data` contains: - the actual version of the protocol used (`protocol.version`) and the other supported versions (`protocol.supported`) - a list of all available capabilities (`capabilities`) -- a list of the existing block types, their attributes, and their configuration (`blocksConfig`) +- a list of the existing block types, their attributes, and their configuration (`blocksConfig`) - It contains all the block types but mark as not visible the blocks not available for this field. - information about the actually edited content draft (`intentParameters`) - the current value of the Landing page field being edited (`fieldValue`) including the layout, zones, and blocks. - a block-ID-to-name mapping (`blocksIdMap`) @@ -377,14 +377,27 @@ TODO: Is there other events that should trigger a positions update? `PB:DRAG_OVER` message is sent from the Page Builder to the front-end preview to give the position of the mouse while a (new or existing) block is dragged. -!!! tip +!!! tip "Mouse tracking" - - `APP:MOUSE_POSITION` helps the Page Builder to know where the mouse is when moved over the preview. + - `APP:MOUSE_POSITION` helps the Page Builder to know where the mouse is when moved over the preview. It's associated to `APP:POSITIONS_UPDATE` to know if a preview block is hovered. - `PB:DRAG_OVER` helps the front-end to know where the mouse is when a block is dragged over the preview. `PB:DRAG_START_PREVIEW` and `PB:DRAG_END_PREVIEW` are sent at the beginning and at the end of a drag operation on an existing block in the front-end preview. Its data contains the ID of the block being dragged (`blockId`). +```js +window.addEventListener('message', (messageEvent) => { + switch (messageEvent.data.type) { + case 'PB:DRAG_START_PREVIEW': + document.querySelector(`[data-ibexa-block-id="${messageEvent.data.data.blockId}"]`).classList.add('c-pb-block-preview--is-dragging-out'); + break; + case 'PB:DRAG_END_PREVIEW': + document.querySelector(`[data-ibexa-block-id="${messageEvent.data.data.blockId}"]`).classList.remove('c-pb-block-preview--is-dragging-out'); + break; + } +}); +``` + `PB:DROP` message is sent from the Page Builder to the front-end preview to notify that a block has been dropped. It has no data. Combined with the last `PB:DRAG_OVER` message, the front-end can determine where the block has been dropped. @@ -433,7 +446,7 @@ It can be used with the [`scrollIntoView()`](https://developer.mozilla.org/en-US window.addEventListener('message', (messageEvent) => { switch (messageEvent.data.type) { case 'PB:SCROLL_INTO_BLOCK': - const blockElementToScrollInto = document.getElementById('block_' + messageEvent.data.data.blockId); + const blockElementToScrollInto = document.querySelector(`[data-ibexa-block-id="${messageEvent.data.data.blockId}"]`);; blockElementToScrollInto.scrollIntoView({ behavior: 'smooth', block: 'center' }); break; } @@ -454,7 +467,7 @@ window.addEventListener('message', (messageEvent) => { switch (messageEvent.data.type) { case 'PB:BLOCK_REMOVE': const blockId = messageEvent.data.data.blockId; - const blockElementToRemove = document.getElementById('block_' + blockId); + const blockElementToRemove = document.querySelector(`[data-ibexa-block-id="${blockId}"]`);; if (blockElementToRemove) { blockElementToRemove.addEventListener('animationend', () => { blockElementToRemove.remove(); @@ -493,3 +506,48 @@ The Page Builder responses with a `PB:UPDATE_FIELD_DATA`. ### Preview parameters update (`preview.params`) `PB:UPDATE_PREVIEW_PARAMS` message is sent from the Page Builder to the front-end preview when TODO: it's sent on several occasions without data. It seems also (if not mainly) used by segmentation. + +## Guidelines for front-end implementation + +The protocol documentation is illustrated with Vanilla JS examples. +You should use a framework to implement the front-end like React or Next.js. +Each block type view should be implemented as a component so you can easily add new block types and new views. + +CSS classes can be named however you wish, but it may be advisable to follow certain conventions to help the reuse of existing style sheets. + +### CSS classes and data attribute conventions + +Some class names are, by convention, only used when the front-end is used in the Page Builder preview, some are always used. + +For example, the convention is that when the front-end is used in the Page Builder preview, the `c-pb-iframe__preview-body` class is added to the document body. + +#### Zones + +The always present `data-ibexa-zone-id` attribute (`zoneElement.dataset.ibexaZoneId`) contains the zone ID. + +`data-ibexa-zone-id` + +| Class name | PB only | Description | +|----------------------------------|---------|-----------------------------------------------------| +| `landing-page__zone` | No | Every zone container | +| `landing-page__zone--${zone.id}` | No | Each zone container with its own ID | +| `m-page-builder__zone` | Yes | Every zone container when previewed in Page Builder | +| `m-page-builder__zone--dragover` | Yes | When a block is dragged over the zone | +| `m-page-builder__zone--empty` | Yes | When the zone has no block | + +### Blocks + +The always present `data-ibexa-block-id` attribute (`blockElement.dataset.ibexaBlockId`) contains the block ID. + +| Class name | PB only | Description | +|---------------------------------------|---------|-------------------------------------------------------------------------------------------------------| +| `landing-page__block` | No | Every block container | +| `c-pb-block-preview` | Yes | Every block container when previewed in Page Builder | +| `c-pb-block-preview--is-dragging-out` | Yes | When a block is being dragged | +| `c-pb-block-preview--is-removing` | Yes | When a block is being removed | +| `ibexa-mark-invisible` | Yes | When a scheduled block is marked as invisible | +| `c-pb-block-preview--unavailable` | Yes | When a block is unavailable for this field | +| `c-pb-block-preview__inner` | Yes | The inner container of a block | +| `c-pb-block-preview__inner--invalid` | Yes | The inner container of a block with invalid attribute value | +| `droppable-placeholder` | Yes | The placeholder element shown when a block is being dragged over a zone to indicate the drop position | +| `c-pb-block-preview--highlighted` | Yes | When a block is highlighted TODO: When more precisely? Seems to be newly dropped | From 3bd6c2cf5cde75528801b0265ba854776d8edf9d Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Fri, 25 Sep 2026 15:00:10 +0200 Subject: [PATCH 16/31] Continue documenting Headless Page Builder --- docs/content_management/pages/headless_page_builder.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index 564b0e964c3..641d4edbbd5 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -420,6 +420,8 @@ const dropResponseMessage = { }; ``` +After a drop `APP:DROP_RESPONSE` from the front-end, the next `PB:UPDATE_FIELD_DATA` message from the Page Builder contains the dropped block ID in its `highlightedBlockIds` array (`messageEvent.data.data.highlightedBlockIds`). + `PB:SCROLL_BY` message is sent from the Page Builder when a block is dragged near a border of the preview which needs to be scrolled. Its data contains the `top` or `left` amount to scroll by. @@ -550,4 +552,4 @@ The always present `data-ibexa-block-id` attribute (`blockElement.dataset.ibexaB | `c-pb-block-preview__inner` | Yes | The inner container of a block | | `c-pb-block-preview__inner--invalid` | Yes | The inner container of a block with invalid attribute value | | `droppable-placeholder` | Yes | The placeholder element shown when a block is being dragged over a zone to indicate the drop position | -| `c-pb-block-preview--highlighted` | Yes | When a block is highlighted TODO: When more precisely? Seems to be newly dropped | +| `c-pb-block-preview--highlighted` | Yes | When a block is highlighted as when newly dropped | From f02f1f8772d1d04d720dde53628fbb64fdfc6673 Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Fri, 25 Sep 2026 15:08:37 +0200 Subject: [PATCH 17/31] Continue documenting Headless Page Builder --- docs/content_management/pages/headless_page_builder.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index 641d4edbbd5..1d05c397261 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -248,7 +248,7 @@ Its data contains the new value of the field with the following structure:
For example, only `fieldValue` is sent when manipulating the [timeline]([[= user_doc =]]/content_management/schedule_publishing/#timeline)![](page_builder_toolbartimelinetoggler.png){style="display:inline;width:27px;vertical-align:middle;"}. - Optionally, a list of the existing block types, their attributes, and their configuration (`blocksConfig`) - Optionally, a block-ID-to-name mapping (`blocksIdMap`) -- Optionally, a list of Ids from the new blocks that have been added (`highlightedBlockIds`) +- Optionally, a list of IDs from the new blocks that have been added (`highlightedBlockIds`) ```json { From 89705ae9eab5e0117dedc482b3b538b3a6e69cb6 Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Fri, 25 Sep 2026 15:39:23 +0200 Subject: [PATCH 18/31] Continue documenting Headless Page Builder --- docs/content_management/pages/headless_page_builder.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index 1d05c397261..0031a18ec3c 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -512,7 +512,10 @@ The Page Builder responses with a `PB:UPDATE_FIELD_DATA`. ## Guidelines for front-end implementation The protocol documentation is illustrated with Vanilla JS examples. -You should use a framework to implement the front-end like React or Next.js. +You should use a framework to implement the front-end, like React or Next.js. + +TODO: A React front-end kit should be available through npm package in the future. What about Next.js? + Each block type view should be implemented as a component so you can easily add new block types and new views. CSS classes can be named however you wish, but it may be advisable to follow certain conventions to help the reuse of existing style sheets. @@ -546,10 +549,10 @@ The always present `data-ibexa-block-id` attribute (`blockElement.dataset.ibexaB | `landing-page__block` | No | Every block container | | `c-pb-block-preview` | Yes | Every block container when previewed in Page Builder | | `c-pb-block-preview--is-dragging-out` | Yes | When a block is being dragged | -| `c-pb-block-preview--is-removing` | Yes | When a block is being removed | +| `c-pb-block-preview--is-removing` | Yes | When a block is being removed (see [Block removal (`blocks.remove`)](#block-removal-blocksremove)) | | `ibexa-mark-invisible` | Yes | When a scheduled block is marked as invisible | | `c-pb-block-preview--unavailable` | Yes | When a block is unavailable for this field | | `c-pb-block-preview__inner` | Yes | The inner container of a block | | `c-pb-block-preview__inner--invalid` | Yes | The inner container of a block with invalid attribute value | | `droppable-placeholder` | Yes | The placeholder element shown when a block is being dragged over a zone to indicate the drop position | -| `c-pb-block-preview--highlighted` | Yes | When a block is highlighted as when newly dropped | +| `c-pb-block-preview--highlighted` | Yes | When a block is highlighted as when newly dropped | From 64076dc93c9fbc2f365c9deb9a5d18027232965f Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Wed, 30 Sep 2026 17:38:34 +0200 Subject: [PATCH 19/31] Headless Page Builder static example --- .../config/packages/ibexa_page_builder.yaml | 37 + .../page/headless/config/services.yaml | 5 + code_samples/page/headless/page.html | 820 ++++++++++++++++++ .../src/Controller/RichTextController.php | 30 + .../pages/headless_page_builder.md | 78 ++ 5 files changed, 970 insertions(+) create mode 100644 code_samples/page/headless/config/packages/ibexa_page_builder.yaml create mode 100644 code_samples/page/headless/config/services.yaml create mode 100644 code_samples/page/headless/page.html create mode 100644 code_samples/page/headless/src/Controller/RichTextController.php diff --git a/code_samples/page/headless/config/packages/ibexa_page_builder.yaml b/code_samples/page/headless/config/packages/ibexa_page_builder.yaml new file mode 100644 index 00000000000..ba8856f561c --- /dev/null +++ b/code_samples/page/headless/config/packages/ibexa_page_builder.yaml @@ -0,0 +1,37 @@ +jms_translation: + configs: + page_builder: + dirs: + - '%kernel.project_dir%/vendor/ibexa/page-builder/src' + output_dir: '%kernel.project_dir%/vendor/ibexa/page-builder/src/bundle/Resources/translations/' + excluded_dirs: [Behat, Tests] + output_format: "xlf" + +ibexa: + system: + admin_group: + headless: + enabled: true + page_builder: + preview_url: 'http://localhost:8081/page.html' + +ibexa_fieldtype_page: + layouts: + 2_columns: + identifier: '2-columns' + name: '2 Columns' + description: 'Two columns layout' + thumbnail: '/bundles/ibexafieldtypepage/images/layouts/default.svg' + template: '@ibexadesign/layouts/2_columns.html.twig' + zones: + left: + name: Left + right: + name: Right + blocks: + tag: + views: + source_code: + template: '@ibexadesign/blocks/tag/source_code.html.twig' + name: 'See source code' + priority: -256 diff --git a/code_samples/page/headless/config/services.yaml b/code_samples/page/headless/config/services.yaml new file mode 100644 index 00000000000..2da349bc7bf --- /dev/null +++ b/code_samples/page/headless/config/services.yaml @@ -0,0 +1,5 @@ +services: +# … + App\Controller\RichTextController: + arguments: + $richTextOutputConverter: '@ibexa.richtext.converter.output.xhtml5' diff --git a/code_samples/page/headless/page.html b/code_samples/page/headless/page.html new file mode 100644 index 00000000000..a69187f2585 --- /dev/null +++ b/code_samples/page/headless/page.html @@ -0,0 +1,820 @@ + + + + + + Headless Page Builder test + + + + + +
Header
+ +
+ + +
+ +
Footer
+ + + + + + diff --git a/code_samples/page/headless/src/Controller/RichTextController.php b/code_samples/page/headless/src/Controller/RichTextController.php new file mode 100644 index 00000000000..9d0d2b237b8 --- /dev/null +++ b/code_samples/page/headless/src/Controller/RichTextController.php @@ -0,0 +1,30 @@ +loadXML($request->getContent()); + return new Response($this->richTextOutputConverter->convert($xml)->saveHTML()); + } +} diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index 0031a18ec3c..a3d1574c7dc 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -556,3 +556,81 @@ The always present `data-ibexa-block-id` attribute (`blockElement.dataset.ibexaB | `c-pb-block-preview__inner--invalid` | Yes | The inner container of a block with invalid attribute value | | `droppable-placeholder` | Yes | The placeholder element shown when a block is being dragged over a zone to indicate the drop position | | `c-pb-block-preview--highlighted` | Yes | When a block is highlighted as when newly dropped | + +### Static example + +The following example is just a demo in vanilla JS provided as-is to illustrate the Page Builder protocol usage. +It can be used to observe the messages exchanged between the Page Builder and a front-end preview in the browser JS console. +It doesn't support all the block types or views. + +- `page.html` is a static HTML page with some JS to handle the Page Builder protocol messages and basic CSS to show how conventional classes are for. + It works both as a standalone page and as a Page Builder preview. +- `RichTextController.php` contains a controller that converts RichText to HTML. + +This example needs some setup on a development installation: + +- RichText to HTML conversion controller service TODO: on SaaS, how to do this? +- Declaration of DXP URLs in `page.html` itself +- Declaration of content types having a Landing Page `ibexa_landing_page` type field +- Being served by a web server +- Headless Page Builder setup in the DXP +- Optionally, an additional layout `2-columns` +- Optionally, an additional `source_code` block type view for Code (`tag`) block type + +??? note "`page.html`" + + ``` php hl_lines="175 527 778" + [[= include_code('code_samples/page/headless/page.html', indent_level=1) =]] + ``` + +Edit `page.html`: + +- Change the `apiBaseUrl` constant to declare the origin on which the REST API and the conversion controller are called. +- Change the `pbOrigin` constant to declare the origin of the Page Builder. +- Change the `pageContentTypeIds` to list content type IDs that have a Landing Page field. You can set this to `false` to skip the content type test. + +`page.html` supports two layouts: + +- "Default layout for Landing Page" (`default`) +- Custom "Two columns layout" (`2-columns`) + +It supports the following block types and views: + +- Text (`richtext`) block type with `default` view +- Code (`tag`) block type with `default` and `source_code` views +- Content List (`contentlist`) block type with `default` view + +For local test, it can simply be served by [PHP built-in server](https://www.php.net/manual/en/features.commandline.webserver.php). +For example, by running the following command in the directory where `page.html` is located and a free port: + +```bash +php -S localhost:8081 +``` + +Then, the Page Builder can be configured to use the corresponding `page.html` URL, for example in `config/packages/ibexa_page_builder.yaml`: + +``` yaml +[[= include_code('code_samples/page/headless/config/packages/ibexa_page_builder.yaml', 10, 16) =]] +``` + +Optionally, declare additional layout `2-columns`, and a `source_code` view for `tag`: + +``` yaml +[[= include_code('code_samples/page/headless/config/packages/ibexa_page_builder.yaml', 18, 37) =]] +``` + +Optionally, create two template files, even empty, to avoid errors when reaching a landing page through DXP front site. TODO: won't happen on SaaS. + +`page.html`'s `richTextToHtml5(docBook)` function use `RichTextController.php`. You can modify this function if you don't want to use this controller. + +??? note "RichTextController.php" + + ```php + [[= include_code('code_samples/page/headless/src/Controller/RichTextController.php', indent_level=1) =]] + ``` + +Inject the RichText to HTML converter service in the controller: + +``` yaml hl_lines="5" +[[= include_code('code_samples/page/headless/config/services.yaml') =]] +``` From 5a258ba2b2a853b84f7ab40dd2d9d21d8cef7172 Mon Sep 17 00:00:00 2001 From: adriendupuis <61695653+adriendupuis@users.noreply.github.com> Date: Thu, 1 Oct 2026 07:35:26 +0000 Subject: [PATCH 20/31] PHP & JS CS Fixes --- .../Security/Form/FormSubmissionServiceDecorator.php | 8 ++++---- .../headless/src/Controller/RichTextController.php | 10 ++++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/code_samples/back_office/limitation/src/Security/Form/FormSubmissionServiceDecorator.php b/code_samples/back_office/limitation/src/Security/Form/FormSubmissionServiceDecorator.php index 2f0328b8765..b231a327a5b 100644 --- a/code_samples/back_office/limitation/src/Security/Form/FormSubmissionServiceDecorator.php +++ b/code_samples/back_office/limitation/src/Security/Form/FormSubmissionServiceDecorator.php @@ -16,10 +16,10 @@ class FormSubmissionServiceDecorator implements FormSubmissionServiceInterface { public function __construct( - readonly FormSubmissionServiceInterface $innerService, - readonly PermissionResolver $permissionResolver, - readonly ContentService $contentService, - readonly FormSubmissionGateway $gateway, + public readonly FormSubmissionServiceInterface $innerService, + public readonly PermissionResolver $permissionResolver, + public readonly ContentService $contentService, + public readonly FormSubmissionGateway $gateway, ) { } diff --git a/code_samples/page/headless/src/Controller/RichTextController.php b/code_samples/page/headless/src/Controller/RichTextController.php index 9d0d2b237b8..b09602d353c 100644 --- a/code_samples/page/headless/src/Controller/RichTextController.php +++ b/code_samples/page/headless/src/Controller/RichTextController.php @@ -1,4 +1,4 @@ -loadXML($request->getContent()); + return new Response($this->richTextOutputConverter->convert($xml)->saveHTML()); } } From a0f4b122342fc0ed310d04b3a869b2266e91e02f Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Thu, 1 Oct 2026 15:27:34 +0200 Subject: [PATCH 21/31] Headless Page Builder frontend kit --- docs/content_management/pages/headless_page_builder.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index a3d1574c7dc..1bd58c0bafd 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -557,6 +557,14 @@ The always present `data-ibexa-block-id` attribute (`blockElement.dataset.ibexaB | `droppable-placeholder` | Yes | The placeholder element shown when a block is being dragged over a zone to indicate the drop position | | `c-pb-block-preview--highlighted` | Yes | When a block is highlighted as when newly dropped | +## Implementation helpers + +### Frontend kit(s) + +TODO: keep up-to-date, incoming npm packages, their installation process, maybe usage examples and integration guidelines + +TODO: On ibexa/frontend-kit, packages for several frameworks: [React](https://react.dev/), [Angular](https://angular.dev/), and [Vue](https://vuejs.org/). + ### Static example The following example is just a demo in vanilla JS provided as-is to illustrate the Page Builder protocol usage. From f92f62dda3719ba6a7b48d824602dce7a27e4745 Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Tue, 6 Oct 2026 14:51:35 +0200 Subject: [PATCH 22/31] Headless Page Builder: more TODOs --- .../pages/headless_page_builder.md | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index 1bd58c0bafd..439915b7a42 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -512,12 +512,18 @@ The Page Builder responses with a `PB:UPDATE_FIELD_DATA`. ## Guidelines for front-end implementation The protocol documentation is illustrated with Vanilla JS examples. -You should use a framework to implement the front-end, like React or Next.js. +You should use a JS framework to implement the front-end. -TODO: A React front-end kit should be available through npm package in the future. What about Next.js? +TODO: React, Angular, and Vue front-end kits should be available through npm packages in the future. What about the Next.js used for a demo? + +Pure frontend and Page Builder preview should share most code as possible. +It could be a same controller called in a different ways to know which content to render on frontend or if it's framed into a Page Builder preview. Each block type view should be implemented as a component so you can easily add new block types and new views. +TODO: Text block type (`richtext`) need a conversion from [RichText DocBook XML](richtextfield.md#custom-docbook-format) to HTML. +TODO: You shouldn't implement this conversion fully on your own. Use Ibexa library, extend a DocBook library, use the XSL files, . For more information see [RichText to HTML helpers](#richtext-to-html-conversion) + CSS classes can be named however you wish, but it may be advisable to follow certain conventions to help the reuse of existing style sheets. ### CSS classes and data attribute conventions @@ -530,8 +536,6 @@ For example, the convention is that when the front-end is used in the Page Build The always present `data-ibexa-zone-id` attribute (`zoneElement.dataset.ibexaZoneId`) contains the zone ID. -`data-ibexa-zone-id` - | Class name | PB only | Description | |----------------------------------|---------|-----------------------------------------------------| | `landing-page__zone` | No | Every zone container | @@ -563,7 +567,13 @@ The always present `data-ibexa-block-id` attribute (`blockElement.dataset.ibexaB TODO: keep up-to-date, incoming npm packages, their installation process, maybe usage examples and integration guidelines -TODO: On ibexa/frontend-kit, packages for several frameworks: [React](https://react.dev/), [Angular](https://angular.dev/), and [Vue](https://vuejs.org/). +TODO: On ibexa/frontend-kit, packages for several frameworks: [React](https://react.dev/), [Angular](https://angular.dev/), and [Vue](https://vuejs.org/). What do they provide exactly? + +### RichText to HTML conversion + +TODO: The frontend kits provide converters. Here way to implement your own: + +TODO: To provide the .xsl files is enough to implement own converter. ### Static example @@ -637,7 +647,7 @@ Optionally, create two template files, even empty, to avoid errors when reaching [[= include_code('code_samples/page/headless/src/Controller/RichTextController.php', indent_level=1) =]] ``` -Inject the RichText to HTML converter service in the controller: +Inject the RichText to HTML converter service `ibexa.richtext.converter.output.xhtml5` in the controller: ``` yaml hl_lines="5" [[= include_code('code_samples/page/headless/config/services.yaml') =]] From 7f884dbc57b4a2da8bb91840a77905f02ffcc903 Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Tue, 6 Oct 2026 16:13:05 +0200 Subject: [PATCH 23/31] Headless Page Builder: rm "Edit in the headless Page Builder" checkbox --- .../img/headless-page-field-edit.png | Bin 47199 -> 0 bytes .../pages/headless_page_builder.md | 5 ----- 2 files changed, 5 deletions(-) delete mode 100644 docs/content_management/img/headless-page-field-edit.png diff --git a/docs/content_management/img/headless-page-field-edit.png b/docs/content_management/img/headless-page-field-edit.png deleted file mode 100644 index 377d3be0995f24668ebcbdf0171d634a56217d8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47199 zcmdRW^LJeB`*mz5jT;+{Z8x^vG?>_SV>E4S+qT)*Nn_h~@|`r#XT5*J`$N{6Ip>;l zpPLu<-U(HZlR$*Sg#!TrL6rO|sssW8S^xq9<^lr+yu!$pP6NDP1P~EXun>_Dv9YwV zSGF}YG8P3m*jgI8DX@TmQ2qA$RVCe{fYRTgmY3;-@);kWIaDMz8m^hM_LHa`jB3|m zY>W3T&|DJts4Z{Lvz9GRA}(uN z>pSp5o_1}WA=;EYdh(kHh&CdG-HX)n3aQs}fvp$*>s7g7&5pOX$gZ#hrs9lPoPJ%x zuZ6vj>Eq;Q=uu6z7lgnYL*VwNt2Rj25DFpp@(otQ>AMuNX`s*+11D zSe6cQ#iDEUBJtY(Wt<2A`@A6VT;tc_t834(p_CDb>v=f%n}jm4ci6U*5j;*qBuFX7 z<>#pj){1;&-49BGEYg6+kh(Y|TXqRbi-E-%UPfjJow}wCT)!EKq*67%d1Zq}h=^5% z@p|=9^NrgBUdD5(-X*eM+z`$5#QZ-4_6d})z-(zwVE?-UT966;zt3PU?>G4# zu7J-J1d$XKQgH=6PJ{Hs7{D6P=j~ddZ*0MIk)l5R61cgjRH`982?i;Z^)*YOR-rGe zv4;@8YX!E8t^VyUWmxa@i_0%Tdlx^Bhiz*YXJ?b!7LTjjHaC{7&Aq*X-w?z^5COg@ zC}47;owK2bB&w)j!h$d`pv0LljYs&GJHrJw(TZ_Oc>R1%%Z*s=hWBBAnFu&`#d863 z-w3U~I zC1*6^kG|Q3`kHS&^kiR1)P|?PH?=gy1Q$TNxw}S(TQqi~eZlJP7%87Cww+QIRD?rB z%rPBLr|H`6Px5ec`<;@Kk}ldF_&!3w_i2p>sU@f47|-CNeC`X!ifV0b)ART#y8$7I ziGeQ@MaV~ijO-#6O-9|+60YD*FUv*s@d9eFt~HGQzua#Q$@#n4sbhFwG?5>+x(P?H;n0${{L&|FGVJgNGIwztLRiJ9V_j0Z8iPJ&|gI3Lz1^g!$EKxs7i_nQH} zd@v!l)zHS&A|KY-Vx541>A{%S>(RujT9Xs^IxUj&ZU$cKlje{{Gu^cRUdfMB^4)II zXkd1z#pCWYFM&ayCUKy9>-KnIz^>vL>HaYi&+&YnxGuGF1s<8Fhz1DTg^xR7I zH(K?we5ADIzbE_x9=8$vM^lmBd-kYc;AhiwR!awuH+b=?Pega}spmPg&z_Q%grEhe za&a_jnP8BY%0C`&B1+EGN;Otd=0WUMZ*$P}rl#_Si*yUduFp3}TN28!?zacgF~xbP ziHHQnUhbzYixrR1n;jp*fcql}WRB>mRU0|EV_m(^s1pmkNHyiQ_1A(!cR)1C{zUJV z6sONAnAPGlp}u;hZZUp0i?GdF)%3m2$(oOEv08;#N5yN;mmMAtVu#%q;T8AmO|gq( z2Z7YIV7|jW*6FAM`HY{7^#Eh%QJkrQC=AnhqIwrsTo>f@v6bJTEVu4%ZfI(eqGt2; zY;g?g@ysS)&;FQm=`NUQ$ft4&^#ma(O`k~D*O|#K)t_XV&ldN8<*NegZS%OJayp#( zed%$%k6MA2!m0EejIqI*tgI94eRIgh?QxqriGYrc{gp9}s8c4?3nFpr*Xd&2k@?!< zKwOEsDsHN2Q@vVyt6QOa9Zf8wp|I28)<6{O8;tA3cq*60OtnhxAT(xlfaZC3pR`np z!Bc`1d|8i{>*F;JpX>n%DI7MM(#4zQx*g?1K9AQ$ivw&&OOKL``3^e4 z;R#=;uTn7epi4W_ugp2YZ0^l%z+if?pX$Y6*x<|DeRP@YXE>dyg zzcA*?#89van5quWbA*S1K)>L4kKoH)IXGYK$~ui)lFGp643{os@VShcWe?N|?Cmt> zpq)o7Px~- zlw?4{cwdkml5oj=Z@EA} zxIN)1MuNQD+iIAgsXd?XW4+tUppv*fUY5Wp9!lnT!!a_CS?~XU>!^si`w)JZfXrDYeSQ8fcwO9RW1^%9S z#_-L7s0x{owTOqGPZrjfPR+_${*ZXzXCMcGYakSD+uc;)%R zQ9^^>_57u!Qw~g(MS6KMH%4LPfxv={!@VNJ%MSoO=>^+H@k*PhY96*-52&-plfDW0H3= zTZ&e_nH;>gZf^S7uXPj}y;khV2NMkAu~f-4BtI_eXR^nw@eY`I*xUQjG+wu8rF@y9 zDUuDlxk8DE`yjbAuF-fDBoan!D812&0YZf~$&JgAou|D_b zvso^y3`f%^)PFxWx$(|a02GmPAJdJ&>6EHhxqz8o6YDH=} z)kflRSiJGriyp1kM8$LKQbeY4so>7Js_?5?%+0+nHAhb4&x%Jpi_h|S<(Do#z+d?t0=8bX>NRKg$==#Am@gQ(r_|ggW6F{^CED6sqh6O;FTMXMC%TxvK90v z=StljWv|t;9mKq)dlzC`brr+*xma`sPGTRSFjQsF19tO zZEbNMreclMe^0X4qG_j0<09l$Z@D|3#pSTdI&8Cf19e&j_Mw*7^GvJOx}=KbCzLgK z`*T=DUTlA4oja7~K7d-OU|y~4RXL3%6o*_oNlm-HTY+6;cSu{IM5ivley5{saiiyL zy8YQa1Zr%-es{K9ug$!4>xi8~=2>qznKY^&H(H9_b$|ZQ?ZJBp`H=tlVsFh;f2jD0 zWw*tSX0&L!V3x0sh4puauI&atX)FMX>i@9C@ zqHy5ajb|LG)-K(p1fb)xvAUv=4~t%X&+jnMOi?Jy}-;2W!iMCSaw%@nsp@Y zEgUVmgI+T~Tf*n*GyH7oV&8CrY)sKnutCeH+s1%Gv5Z@pX+^sU!1;8s%y{Rh$#$|C z#duU@RsxHeGl>oVWQ+SIqPvKSqdl&8X5!vzDe>-Psi7{_?b5>Q(JO1S-+I2smD3GV8o&&EC}C zSQAVe3kfW_(kwH}a-}K*;e~;2~IO#=cdAmBavr#4ekEb2u#zo3Xx*f_OKQ zppVv$%R57dh&-?0w&5mXa8=n{FYxxLeZsJrz`&bP(i8ZJFVS~;==UbI=3Kg$2)^G}~oN*GhM1N8Et-BQ@FhN8)99_Nv} zWcE)^j9A+`gVGa5o!d35_a$dsxY$)+Ztet3?DBb@I~AjILyK7N))Ip*cZN_cL>;eg z>6=Hr=naXpAZ(yC{ll?LIRIvw;rRx)VIRvm+l|-Mmg0&H zh!o@XN5qs?_<_e$bjf&up=IbC%2!wxV z@lwVO;FuBj!G8=gHiPc|kxr;^So;HiDne`O?0%p`o@9q+OfrYuNvED#G0jReDsrkm zb&vew|BNQMLw`xr=SD7@JVVDY&0EVTn`8&SJ8lyJ6+Tm>jPt~+x%6$?f`mqErqy#M zrS6l)P&P()BG)1a?^Avjn1D;^BU99HESECH>{}>%H*2R#DzOOE4KL9v#yquH*tSZe zE%EgCk!s!x={#nmYZW zJDicW-93d%-Z!{f;nPuEJsjF!RoHZNbw-P~c6Y7k2-?0Io z54D&+3&msUcHZX3Nfqsc7`XTrl3;M1b#No5x6eX9;*}0#do7sizN#|P;?;=?n97xu z0udJMqJ~651BXUZS=!OSULx&mG6&XMOc<=Gu)GZ8f09>e6JD8)KLesxqPM=E9vU{7 zx!%D0NuU$V#Js-7@_C3-a~o9z018Q!$dr$nA4!c18LLoY`H{6MW$Tpjk^l;MgT{fq$-e$3!82%7JvNn z+eoEzyXgyHe`&TGQZr`SS%o{@b}r|x0obR$lRT$$hgcR%!xDlbCV9OdOJupKV?YgBx7 zZ!D^R{639KiA*ylD$E>Qpj~e;Ec@Jf1=s%*Znvx;$GmH2Gpob-q?uV@e|BQ)9NbZ~ zbF^y-Q3l+!sY>iexKAR(x{_|~SHqzM1_mzov%@KT$2I5E44FZOlc?AW* zJDUAoIs)E;q!N*e!jS%9pJ~h$rJW?bJF+L23WjK@|5i;$tM0gv2T|F)%6r@ zbx><|VRH;xr>C1y_P7uhEGXHtJ5a1jGhLdohjKSSb?2Q(B=PfAE$Jzn<~s9pu6)8z z8uemP7SmCsanK;R^+3=YufEeW#nE9cFGGr;2Q-3$LRvlE^@saCeIK!-MdF_Gr;T=P za+P!KPD`fch5-gY%~@N&09Z7I6D_udrEB$_q>#OUC$hNt!i~NOB3MJ~FFJ)Ni1@4l zyCW&`+Vz&I07mj;G??dQqT27s18H=f{Z|g*YwRPL5>W&Np!!IghR6x3$?yqZE{0>U zQec$}UtC^%T{a3byv;FW+`XF`KNt4L|3K#BjNGmDc@rXtY)@WepH{rH&WPdQP+9Jh zJ(kS%R#<6q+JRnP)6`4$aj z#mvx4YBTK1xxx!NzvSj%I{DWw=APasT1u;ZSz@L^p5c{At{U)%sTEL=CzHf%Pbh7{ zuI@(dV%Zw`6PHVejmS*2J%jV7`|YWOtah!E@cB+jLUG4BW>n7P(Jy*!wPX%cOgo7V zG&q!HGfwxL<8mGMo5!A)&&NS_;2alE)X(C3`2nJFVV|tbqcm$wR9pWlPjH&?M2zwi zQ|L^XDz|%T&Kgv6WZCn1ckUqUuc;^5EAX#Q6;uv$dvs85z^c17%4{WB&eby61q;jr zm~Vh_9ML)I5G{UtM#A6S^JWjPhBsCPXoq;5 z`{t0vchTk8as=KVGC3WfCq&_<$?xL6`n4kCNB?aBVL=fW^TMzk-y4_1wu1Ftk82?) zSUN3Y;>f{B}Yr8BK-I4=6MqD8>0xzFDVr zv1-?g?0`L?3{CKkl7$+RiH5bGX?z}Xh@FrbbR(!QpcU}?m9~GowN`$XrObdBM@;((4viZ5 z+MXGN^)`ND&4fn&oSndX&upQlpZB1-3qOE>&?&YBfsTe-bAPc_^c2`A?D>-K#g5GZ zfsUbZWMunAj}>9F54+@BsbP<$KXt)`VN?|WSb__??k|OpvJsC`xkFm~Y+~l?E8ckp zS%$la&HVy@DGgTZ4#NV2$;s`@HPRh2-J{Bm3b_iOD;x-in}Lde5=@N=#(>U)wH^qL zi_t&U6%iuTOZg%nZG)*V6;DTve2%njdXoGN6cG#b29i?#bPG&++Lv3HYBLZqe_H;C zO@&3y;QR}#WUHqZ6hg@7dt;xzKt9QXC{^0OOx?j_sr=GS``t}bpPk<{YjINU9s08He>U zYh-;B;@y2M@9MA7TlVQcehrkJ3@rT@7R@ri?2ABU51*?#CDf?5i;iex1!ftsao}_k zJg$Uo+1;>Wt>p|PCCPa*7j`SM{3$+95WHupF)!&4v#!c56RoHX`y`oseCi(5bI4{D zMYmCl+1cw0tJTo9*^Q(IE%KKQ)xVDQPDjqC;f$_Jn$mj+cFkAeEHmU3N4}aI>-gP> z{HjGtNo>lX>fh-t@(C&c;bJZ9s({Xf}ypPoHcObSwB9gpwr z(g8-`UBcisW-4G58)a&BaB*~o{P<)vds4}TsJ?+cGr~J_K&0b0=chvsFl!2KI45QQ zu-GV0S&%Ispik`-xF>Qx<}69&W^5a-B>oZS5?v-|n^?IXrkx|sR&qKy=?AvtBX(-k z&6%xyJQ||euyMla`B%XxL*DVSMkd@sP{L=DL@Z*OMl=8S%U^PkX=8GNtG!WLm`bQZ znKVYeyW>?^Swo1ZKZOvrLX13W#)iH{m8;~L^d-IH{P;eM^BKTGu`##5K{tlJyU$e0 zkgsIB^$NEf*XpILQxyDw-S|c6I*xxRW*6WwbrVdmDCYwd?BxZ$=6VRY<9Z0b zbsNzy-~JDxwTlA+hK=rfxvTFOpx<30@ax_E?ob}=I|jIk016)kgDPjYJ0>ai57Hz= z0!5W09BYfG{R9U5MK2BzGTa;~iw^sTgY)BqsRg1(UA@@C{E7QO#(hO#HPE@(17ZxL z6@%y0;IQ6*25cxDB$oJDTMo)VgtP6AcN^>jFzpP5)%YZ5j%jV-9*?dcq9XeNJ#G?! zj^q{AQott}>2h9pn)4btF1JV(RsGjL954+v$P#-}4R>x0EIHm#3WljNH9u9;!QlVl ztk`6}-V{_q^%OW9aFo(TI|m2lnDEo;u@PO|l4>95=Q${PCo`{x&Qx52ShZuoL=|>m z41wWeq$+IHHB-FmTmn7^-T5fJ8`i!Dki#y0E0XpS$H{yRlgb5L`)UCC7G z>3UL#(+Ln!a(QHBA8+8P0g*|brB6*pmN@U=k@pzC`Or)1QrDi4H~PhY6fY1x`kR#t zvR*B`@Zn%g0e+5Yp^wCO>^AyqE6M+$+eXRt8)iY5&L0OzZ+e!ISHSdBhX$!#970r* zGiwX(P`x_5@a1dfod6V+z@SXmn*1WmH%!f!2_dAYEgW$qzY! zk)MDdJb>Z=(e%(X*wnNgFFnQc-%<(iC56R?L`!y!#2ocaMCMNX}ICF(i7_Sp${2OKo zG)6e`HZ<|B0GOEgl~!sFe0ZDj8|5+|ZTaiD?m>;Oxo|j98f!4}Hr~m4O(F1+5WVi! zXtY4&8aU|Aq?rw~sF20jF=jm!KFPhrb$}FWJ1P>En6mli=#*XSk&#B!-{G3EgFhD$ z-WWsKO~N^ATTyCBjz zHp-=g8zmJll52b;)&XtYi+k+L>5-^LTgs$K2(xI^$66FZ)K7s!q8M*#+Q68ble2ey z|3VGtkL15Sfb8q5X<=EP6P|ni^_7_qU($k^%d8q8KGAH;EPdJh`TOuUvS(@eB6#d$ zJmez86(12JpSy$rp>~*NDt`s{!JHtzHr~P69Ym=#?yD94buO^+p3gik%B#F?)PN~6 zbF~PUVb!sJM1j@4%tutEFhKb}8vX>MbGH{zR95UeHhWy(26+-k2AmO;Yha0B;; zuaR{;o=E~CV}hsF<>JVl9(Q0xfUDhFn>X*vYXcj>RP69KWI{fb2OlO|BHcFUxOBd) zB*t|T!f<1$)hZA9z>4!YQzFa^(6L2U>}097u5HrRP`+tj_BA?emqW zYok%`Wq{<`bkcNz+imy&tNo1G4uOC}KY~;oO`yy?LdJz~LZ~t3m67CjCZQkFX~ws9EwI#zMgB@j4qAZcXg1cuY;3jw6D5{04m! z;rHgS#&_&(|{m}c-!N3PJG$ogpG8< z)Wa24q4d1<^_q`%+-{wB4~6+sJGgw?bpQdctDx1QbEeV23zgz#uhcKuWJWz%TRaro zsMa=KguoIDxQYnN;5DNSL)W>$AGWUY8K8;l5pVTAw=|)HhN}@UH1Ox4FhF({WDyEM z1fIKSZ-dh)^=6|a66ztwrLxBcUQk8IXG>zCUYtg~Pk8BsBj$z}QJ+cjNZ=5&Bt8uc9#41}`@?VV{QiFqO`@#t`TD@8UQvtB0 zZaca1c&ynL^X1d&X-j`6yMy7d=;eUOYR+Pv`2-N4Q>@As+m{|AtkJ+1@b-`YqTl6) zoTEr8p-`kmUMRIQ6iesEY&=#|SX?z${U0@p9mW>jhQv7{RAty^>N&*{cUog9B-^&y z+1wRh>Kpa&9{UY?(UvOA0D4YjV`B?|k`AWlcRvMgS>Lz?LQI1D*R(S`p zG^$EzdtF{KdD8K@x*oU1FDU#RK=3-2Sj4>!*&!A0j-&7DLQxpiAD+OEK_6;zG=<|} zqbHcv_3!);9ULQGa56(|d>FRXZb@2?ItCG00o5ib&<;}Rxicg^RrGowk-#{2{zlZE0Z zVF?6kJe0Vvg3^I2-WdAF78Uk|4dAHZhG)sjmT2GAPP2{=7DF-_C^h}A%6TAZ*KU4B zYEwuymyKxrjpz%Q4=zcBu$0){kQQ(Ya>8~bAiY#VlUAO zJL)JefReozFAA470-NI&x+uMHDWSBm|aqHZ^nX`apE!hMvKH zxK4KDPHlLO%{3C1!zP`IOf-G-jTQTqw@2^$r~KWIc4GSdku8jjt-zAv9Au@f9sk9n zF@sqH_3)IT^3bm6FvX(u4U#L_rch>NYMb$|9Qa z(j+zjT}~u_*M1P&XhfCaFO@xsn1-Hjdgrge3tpq28+h!<8Wf&a{Mrwki3v};HDrMw zzF)Lyr#5;*3In{30DejlQ|@boWrS6W9k|3uUa(#&lUkIZ62um0Px&h#NhT`6=A(Vv zZ(tRGRx3hgu5Z;v`o^`uriBT_o4#W(_iOO!-&kp-Gg1FcBw*y}>HoPf$UgP8_M@?0 z1i$_INzAf9FbV4R-=*v%Hs+1D69}UxuF+qW_3~0i7Pgo!NOD3v3G!j%7CV zsn@B$niRu@zmpLgV}^b%0o8N-Z;N$aKtvFX+US0wJ!z7R9n2p^Th-(wHf_CX9M8Ht;xwI*;5a$uHnya`&AkS=~6I|M3H=Hf2g+o)w#fC&*9it@P z2>r*A{2L{RB7X-3xdFt2wtK+8P3OrDpxd?7_=cH$b`&zOPmZIC$(iFYQsF!h(@^V8 zt`trN)*Gf?f|04{$8!<_^6LKEo3;pkt~zv!h9i>hPq$Xht_LK*DvVg!ssTkN9iA)R zY~(j)JkzV*RraXfbx@V5%QsZ{UH7*xuglSBF$iUZ>iE)sal)A}NXc*0k;LC<z)%ir84iYNH&|0g4lWH3UsfLfN2vS(n`;=3`S=EY zwicDE)0>M@?UaOsDmRh5+;l|`WU$sBl3#oz80&&ywrbL8G@n*XH!z$ALJ~_VMFP;d zSJt12gg*9iY63{>Em3Y|abw#L;4MtB>&>D`@{if}y+X5fa8NFZ>XGbT?IP}mb(XQi zYPc(lzx>w)8zEn|0!9{>wuV1j^m29~w(jBXL)0G)pMwG^qSv4+mQ5<}D_T&8n5dh& ze3`na;C-R4gOd<-AAmP6*cbhaU>k)61C(`|l$GS)jXR-51p}s`9cy-!fZ1G#2LzCV z&~>$}>u%Kd`*fyg+C~OT9j%vo!*RV+XtB*SN_XLlR%<}>-ErAatMdu>sD9eSY zN3HzLjVaylIZJ|PPj5k{gJ$!}gQKu#Yo0oE_XmaW4>CXBgC=MXs;`I>l%Yo-~8jnMCG`TEh z!dcUdE-;1V6ep5DU1oK;mA_utTTvNx0)>n$!h)x8;c!W2cdAaVVg0F_JbKtqz485u zrW=`ed)5)_wK);U2nX`&WM&!-!58a|cvOpY0`0$#i#zO&7Hsx~O(wCJnhlKU@?Kbe zGoLKQ`9$?=E%D|zsf31?p5!<%*1n=Cs*`1Gz%Z$Gy+0=|)4GAKvz$zYRQs09;=&K~ zXVK4c>A66529WAFc(1`Sl)zEJ)bUnt{m%Ik$!cA+iNu|y22|%dZahPpuM`{SYBImx zUoq67<#EWLTmvxyWh(ey?mB_|WY2VhQ%I;O|G7kZFc=){faMEi>-nDWmmAq zn}Ac)$_|qgEzCk(FP#z!@~537tI`?m3dCesLSS3G{;6onWd2`u;mc1JWV?WM)k|KiWL zs^Z~tno+H61lFLKyzmACDZX*>U$ljalne6tJnodIG0XOWoZ`d#E|K6up_tumpF<2n z`FF;lM2*RtjNZnuyH2xbpt$!HJ>)XWH5ZV@OLsW);GorH|H;t(A+5z(u?Dm3K+V;y z0Sz{!Ca3f~(qQeC<& zZs&YWG<7(esA7RH5Yy2!pM6-Ub)&^)_aqy~e+H2>TL}AfmdIQ89prJS^E zvzf>sXk+eVaT=It#kpNF>!Tk!zH>o!_<=jrRu2qC;c9neGvQq9T5{!aS&q!0i*=`M zD$()r3<#1~4ahB48`Hit0NNDMae2H+y!gK5Hv2Ui*f7|1Yxh@^hsOp@6^ZcB=+=XM z=JyO>&Xt#sp^(q>FBN;Kdvsw#X9y6=GiTF0f>mwJG7r-A*_@V|@ zs=G9It@t42c)iagrOUz=`FhJ^KAR0Go6f42=JRy>nMNBJ#qE**DubjWMnglBVab=x zYjwLSBs-YO%eesZ_G9`H0V}{{X5Z&6M|Y_~slK%R@P0i@e_G`8%qjNyspb%Rln zaxfCB^N5)fzCV_e6pDb~Vn$c@(?*X(t-}(gak=RCHmFFz&RI#3{8>6pq$h9#ueU-} z8;?p2#!wdcEO1X%c|F}JG5WoFq&56!dgF2v_k0G^$h;5a_qc zmFz!Kp4Yp;XDc(fy^>XT+@;RfT}kxjz}+$@8*nuQRm)Yn3N`a&en&s$L{H^NL}_Zb zh#>z(_*-bmw^cOZOk?{%ywN@8O5{ljR9y_kezC%k2`PU%pu_;iOKd6Hj@y3}fmvIC zBIAZ@nmj*+j0JKRtW7tNNT`qlg=#FkA5Z)A`vMn*Et~PmnT@;Hl67sy_wk ztbD_B5OqxU-o0LkiGi6i2?nWnUL32HRzH*Rq$e!~e#-V(4z-iE$yCNXo?4RW^`WQx z`FmtPW7sT#0cIkCaDZW;9;aX;)bY_?O25&Pnl}~VUX#6lCec;VF0rpAWa{3bxgBC_ zRI`xa=Gw|8?riKWT_Vad-*TJ*Vs+vwfw8;0YcXr0E~in@buoifh4e|3g(B3?7~q)> zbS1v(1gV5N3lD}<_faC*4DkESmcLs#N7!P5@vRi3A8h2ID5T=5k zd>{7FZlZGlE!^81bmAO4J)DTXu1p(^(?~?^2LFi{ykOYlnEDByhd{tPyA?KzT*#wG zgHCse$NiWSC>Rid{j#m;yRuGLV*+g&rNw4Z=;KOkG9E9>p!BX{v1JAuqOGtIxB=t; zkw!S7N1Talj^uFxq)oEZ8%dPkQES+cr(MHsjCt)(7~--xgIRDvDdXX8p!J0-#?i!4 ztBDrp&~ zJ2vuUxd>&k=9BVJBGV5VmZs1n4C*&AjsWzIC?&*dOTnYG^-8-KD6cd)YY1M0wW5+US>YcquGtc`yzm5uX&>!|;(m9* zHU1$*5Pw?gJ4oFY?=&E9T&Brkj~UbBfQ2}#}Dk#%=4CWS3B&C&PC1h}`vMw8jH zdXMe(syyA?9}e>_6Msl^wtg?SCzJ;!+Hnf3-wUb7JElDKOfbch7Sdj}wAf;)k&JR4 zZ;oUYM#1m7i9G3glIxCQgLPxX5djZjam&GukFbRE)%RNV)(DkxIy(fT0j)VyE)0Xgi*5LJ-pHP$841+CM&1mM51r`dKofah1#+ z`_o;MJU;=Co#qjmTgr238h8`970L?nxwW|M#nqMaXJ)sBW$=xFF&EZWJ-tbEe3}L- z?^G_2_^BFLxX6omq6ki^b!t}lmX^#M{>rD$`)Ro}#@E$;8h zEe3MX=6^r^WPCM$>5nvz53l9rbe$bCR;e}HC`|nV_!ptd2?>t4%h}=OqWz0X_sG_% zYV=Ya$X&*kDC^KZ5QIcBV1pC@DZP)t6@?TijOv3C9~6C$^v++=D*2gNoGa#m(eGA@ z|LPr#q(+^wUP-w;j-R?-qS1E)Fe~x5Zq)MI9oo= zDdR=}PA!Y+SZRDsClQ0pEi_ApnG%ze1v%mS!+~N$gTP?QQfl1|<6!HHfW^c&RzOVJ0Ot^&e!g z@~$w$GpGLgVVx}nOea(%CAt3_LOdYWKx;*E@`HbKB;08YTn`I~br@tH){5`zvpAP5?Y(b;Fn=R`VJKU&;{89YfvQ8G ztS&A#7ybPv3}_253;ND6qx9>;TJ#+yD~yhI{OE=O$Gfa9NDJ=2rTG6*r+WgXfy%1` zV0l@M;d(5s<$8YYZ3~)B22+&t$0X1!k!k9`xh@c>2 zZ;U)r)(aTMXF)j~DFsE~9E>c~sFYi3ik%>Ni{paK*iB1MkKQXgwxXrh7k65 zcjbU7V;;6dKF42-RS3K>~nt9P6}RzRQs(QQlzmuEFI4xiUCvH5miQs9*} z1sGA94NmRM6uehHH8O8i=WaNWTpXC$Y_+ABEiVC zLN{UKZ9u=7TxTvD9EG3d>2@`7P3V&?xhAisFjuN80YtR2KGCWx0`bkkALAW%SNVrE z$pU+(i#09`Sw7PLm5EyU{9tajPp(||SbWlXq7LVZL>x@taxbOQXxO|2oM_xC^Q!?@ zn9ZI$G%14=3dyWRaXnqNI4ppPPQOyazJi$|rO6Q-0fnIJgCd14f7Wl?9CY}sxa^LM zWv^EZV|VC>3psd!mA04X=L-JCQgKp_N4HjE2~VNzPw}l@o@StTTy7p7Kz+v5@8 z?A`VBH6WHm%-;QVlWX+Nm>9^#3ijl*0xH=6H)q3fMJS)f(&=emo~LDol31WW(Q755 zkxK=b!G0Vt=kXBuG^sk8Mt<>j9P0#Zh5F;Juz~PcWY;(w*pL3K^bw=BS2Gt_4Ejny zzBUynXGmQZqtv)CHIU|hr~xG1QgMkYceokI6MV|DChF5TL=Z1y~GvG>Fhx zlUY`HxFVBAv;X^F0OzwrbNta%LN`a7Yg7?ziR+mLkFlfnK&oRt`!c0!hn{ZUEX276 zc_PSU6ojl4^55Wi@GOX|1X2(7N8=5Wu<_jv%+VC;QE07CV64ShscKl3K`(nc1t{h- znf#+^ckl@dib;^fbc6zK!ZoI2>)enF_!)WgBLC^&*H>T~oz7Oh$f~~%dU4n;i~m3@ z>s?tvoUB4)otiPwa9!OQObdtmMDsO?#W>#!8YvpuPT(-C`GKvhEgs%ktUX*0-uPe@b8OXv3kjnm&mG0tA?U;Wupl850y4^ zRZO`qm5AYy-+Vm!dk&Ykm-#fRG&RZr&}SVg^SVvnAdM+X72A?8PnR0rK$@DHXcDeR zl9;QWou?>k`xPdh0=^cF!ugY2^3EB`|j@d-~-M5#c*bjd3Q z1HLl@$NbpD2Kr;W;~+_=fAJw9*gJ8gTQ}YUz>x3) zp12zyJO9q-{Wkj81}F{?+1%lBBXReSsj0%8hI3G*qEE5&;_iJcjKHepi)>8Jzm^jz zd{v1UtDH7_LubR_nbLe5uN)d}yVq$;U5`eG)j{Ca6U(nKR^X$r|9h?%m{2L1pin28 zpoSckSF@w}TZEZBWGneE-HyB_S=1bhmV;v~+h!OE;eNg1>Xe{c^`W zpU#*67=B^A+r8J`tL8JG`OF2`bcDtcT07xs<2MY7<#}%w6u94VWsFI~jx{WBace?W zaI`tt)vnN79BU8L3QHaH`24Lyz~t^s&_-wfIxBd@bRbZ{ggzClJ1$slo5wbMM6Xgq z9LxQS%a6cSD4Dpm{U^GiEFtKgPUNo=|5Q930IAu&aHam|9AFN?N1&npg>yoBZ&m7Y~p!`kw(3FfHHJ8tYXcp#`-rrJHMKC-8$a+ zkGa{=Zis-P@2rbx^fUPz&OlNJj9J|`Z{MGXb~sX|E*SfWYt5uisg9` zUx@O>Rz&RYZ$$w^3xDP8rr3`&m~Rkp+QA)PsQdfg??$Oe44p=|nZRQ4n8;!O z_*){(E5{jbyRCAIb1JZ*$IMolir!ohW%%4m=K77Zq{<&>EBb?l&^Ngd7=@!Ck(X@C;JYV(Eg z`|B-Ta_7_*XJJTbE~tDd+*&`~W*sjRXXWu);ftlxNe(9zlo`~h%DHNxle2rHf84%! zcRdzSX`*<4dqw4Pygpv@7nkj0uUtJSSMOWv{gpWmI7^XP4fet@aWAi(={h9-6;brZ zd;)yPgK zZ-?8;h;b+@5L~7B(wxmp+(gxaRZ)f8gs}(+1{#tvKYb`+C{emu(^wHf-q!kEDML7o zNzvpP;{GtX_GF-Z^CfFfIufkj<)51^CaV{qK8xL+&(B=g#Y%$frXKtm8~=RqhaEh> z*Zq9&da2jFer|wNku-Vws%R+97W`O1IfS=XizZ{EiwVJ@mU4Om^RcT>dB^>uL8zCe z$W)2;8p=D|Y9l@Z;`HFQstfsVEVsIewwt}ez=DN6jvD`A(R9P`HvWBL$v;EOh%C)! z<0(Wm&UoUPL%wGs5Kq{)n2VOnMu{qmTJO5~yxMf?D=4fUxD$f^ICoB1Wq%~%Aj{)m zF6;HT;d2T}qGHM{(OAacy9md_8A*UAa==F3m%@vSjK>xU3KacS?v5xwX=I%GrqF;1 zVyN}mc{;Lf9Ap8^X1~X>yaw(7NdOq;UZ+b0UMM!nqIzqEg57FJ8j5kwW7-DkRR?BI zSlDE+HpuJ<)9KCDSV#h@=i~nMnOXjYam!twNY?lI z`DAXp(c|ovUtfqmjCKzuj^6}m`pbFFx$B@}zykvHNfz7deBjSNjTkt3~_v_EsrgYSH~l>4e~gv+lRv#zsEF{Z(L6A-P?L zN(t>YB1)-Lq>xgeRPvUz`PIvmu`j0j-3>0gIN7rCLoc?RM$-zE3WdFjG{mjLBf+Kt zVJpyKhjeSx8`Go9;Anod1NF-cK5we63E0pFNMC?X%c~K-#X0%`J%pB4o-6tNZE&7@ zT}24S(b(Ad@fuYz=7#+G`*QVE zqd4ZyXkGM6__Im8{@{N*Z6@q$jP>dM!6;8pNaz`U1tgOu`d>k!(*2vRIr zFAo*5eN=`*e*hWBpXvwxvv$`#a_1-jI16g=P%8-J+JhkC2#V?V3* zl^p^RD5WS*eHmXW!vD9|Z;_!{AHHH7{wg;pYj*gO=Pj3ui|a8>)z9BxNOW`W?|G~! zq(0ID(-eO|WSlLem&o}Z7TijUieWnC15%6oMj!9s^)kXog@;uAvIm9tw*P7VBH#4; zR`fP~KkJq9_+U!fMu!^??ONxrQ553ebFka#P}E+&`QKS@D3bw~?tXM(rZ#>vVc0*YkoHZ+k0e{2sqA0Hq4yKdx(tL}r>;j6DV9$}Oi48#1Z4q8U^3uf{UUC_JB z+$;doY~up4!4YaH+O6b2*69Yrn;oegacKw*;Hqt6;(S8-;sDJWlGU!@}u^T#mBlN=wPR%trC z5^#O1TB4Pa%xxPP5g}XE*W|<)c`#r1hTCqF7!@_*V+w8X;|nYg!V-Mv4*2|8A?chj zUuou8DPIGbM!N(img)>0nTR_PB!QdjCYd7*z*?@9p`gs;b>EI}cOvMJ2&@$Ram1fTKyJ}bLt7{XNHFaS6kR_eODWCZnS!wqAY)2s&(8r)c`2T(X zcU(67+FDvv7PD+Iv>#-YcUiI}DUv=bUYna+VfsD8>6P8DV?fgy>BG6N528_` zlHKJn*HhGk+M0{pnYvR-p(J`-PxVr~-we3ADz~?{pGu!;gZx5YDnI`ILXGY|D!xDz z$QOiyP*QSU8YneAyEP^~c0$UjoG>$OYalZ+QVwv5FWJpUlW%WjD)eZCB;$+I z&r^8D`r{e5+kpPi;re;I1DSMGOe(*d1f=pZS3TjsMR*RDActGM5ChgbJ~!TMnn(c1 zPd#--J=`v`Ku!*TSh$ZH1rrk1!fUR5A{&`3*?B{h)%k`ujx-I`yOU$TGJ8z7&go+) zoh-3&F)+SM1-(i=7!PMJ{n`tdmPfBEEwdnZT>fX`8A;aojSo+RHLBX0atrEpY zi%QRAnI4(s^x`68WPBDeLSDz)TArSc4sBBdw2Dw%`t-MmmOA^;LC}+a@o$rFx0lIboJ!PbHY zx^_%zD|BbK-YesEdxg8;^~XD^T#l#bPKt?Ar1i7u)5`4bt=GRdGWq_|V|q#69sZcG zgMCY0sxOEA;8C~Nsl6=6pP0_Z{Ol8lL3WwrC^lVI_1m5B5RJ{Dk1VzkikDj|f$dwp{l3fs(2%@DCt$Wl&UuH-iii^5wU6(alyjD(Ux+4LUVT31PEDITEogFi;L4Vq}4@bPJuoKRF zihSwpvQdTB?h74`I8y6+`uiQST8HmUkxFqQpv3bV&j8Kc2UCJgZbJE4&QXU-^?(%A z3{=-YMR@+axmYV7W}((5n*VrmtS0l_=#1UgbQu4uu+95i1#-!}DyEAzOyJ8FszmJN zc|4f>4TDlfipWFh^KNRg*+kJ$;@F$>A>QFsXNT?G3_ofeKBDZEI_4e;Y#OTf&+@F% zq>QilPLuwd*d)D#QXipcvFn}Cv;f?V8Kkyqc9-DN-+X%7lJ4_Yt{sBAEgEF(^$r>O zI#b>MlO=k>E(h$d8CnycTnOer3;%suuFIcXLUw8>{6dq5k4sxLTLiK~`k?xQyiW5k zh!#3*cT(>9bXy>Djv@X*6>n_`1K1jC3c3UuY9K-yQXj`J%NGE*wV*1y=@|50&s8 zY=TrPRV{a2 zr5tbW~0PM?sCFSDtkXuvBm->$z&PFwyk}-v$58x@9fcbm2OE5*3ak zZW0KQMPb93D$MsO9k4=8!z1`p8m7em`B)TSn3NtcJ7t(9o~M@#J> zN4fqZo;)DP6!inO=)VLaFtk);(-T*CTz1P)0q1zWLYMsylCXiRL!Q!!KTx4)Fy|oB z*hWr%GaWFBE^u#^7e@f5618f z2Q`1lt-V9020}|V;DDu6Z%?h_5%CMGn$)itt*6Vic?-1azBBJ4<8zGqiiT2iQ9-C~ z$%t2iDj-|912R{qV?{ILrMg7yDYrF--3oQK#@ovo9aUCKo)QU6&<=YesWd87Rs)AM zR7bsR_iN{V(<<_kD zG&>(*NT*$4CQ+8kN0EtNS`@Nk(`t;XeV74DMe7wpmP`tbmXHI56zzC{sNK$JaRY`F zX&|ay^RpJiFrcM4beM8Yi+8bFI${Mo1*bVs|cc1~v15`6wT?g-C4A;vIYp)A2gqIJ)Ixz37Rjx)7>* zSof)9;r*rJ2JoolE>O(D%;!9G^-@_fg;qYaIa;E}=M@6m7BDy*;G!&b)(?L$er`{2LwKnfyG^+%hO~0) zxn7uK4#Me%P^MUZ5fT9b-xRj80e=7eDm=R6>x*2*mfyMIoMzMB5}rz_?v2QW>M~nv zwNIJ6e^wmiI{cYWHj4dNUDPbuxLnV0OOvQRaO_ zTKetP2_76~Sq#16=ctMq8agRfg$HF}t zW>Usave^=GBhi%<(UH<_h}(Fjf80U?5LB)M%Eq4f%Ys5Ai%s|yU(VOsOe=f|2t@p@ zQcUWv1Xp@CYe;}(a&2R#D9HUaQ)$Jw18i9f-D)#q0tM*yVx!>IZWh_=o3RCNsGZ47 z+)s%q`A-UDNp7-NEYW|mv6n7=&utTEpH+QFLsqwKif@R@0(qK_jyGpMi-Cy zF3{`6uy?p1tYyp3=o@>wC#%0|*L0_%PT5{;8PP8Dq2dprj~MCUcDIM*K;LLZna0>? z#u8ze&G$SlLCjxRn6DG;OQGAv!~s0iTk8PC)yhbN{eyDA1h%53-);2A$2Y$iN%Pfd zQn2|AO1asBXX7BSJ2@Jv9#g=ORRDGj6l*Jy;||<>OCb|bq)$E|TS=~t@GM?U-t>Pu zui^a;dT{l{CplNO2K^`e%gt1rmXT*rr9AymgU>V+Qnl)0NJT!@dV6RCtqAtSp4f>ddK6X8AeB|_Fso(lQ@up z_*?fbSDzA@5kKdhp{Nmr5eq~YN^_+=C}n8%{aF=(=phIEw=&NF3me;j{=mZKmW?pY zHrwIy@|?0H=IezQDwX>lYZPjglYm$ZBqhwUyD8d^pu#FjrDFaV5 zlwYI;GFj{xnYE#yDw~aG*_)0*m;tH};RM}0PWMHa5%JSS*P{Z)lqgyqpU?2~t(F%1 zghh-=9;Obm&(D`rINS+H0v*&|N-(XsoFq`*x>;+p8V}@M8<;6^p5p3L zz_Sg!d5UZle|!q`6?n?8q#VgZa7lr4M}gQ!{S0#)TIGr?TYlLzhLoL-I#8T|l$|u5 zuA>dq^yJwew)|K3%#i7+JsU6g40OUFDLE-`@>)Sk$=WARV|YI5XLGkyX$d6b0GYQ-mBz;sInC`seAT@(KOEswbGc^(Eg{Utt;Q;TTOYTSd1a`bo zRd}z{IWkXXxlWy)ccX`78)H>O%i_FbDB2X-~9< z*RC$}%HP(?oZ>1MX{7YU&`3v9d9{&ew z9?(yUR%~Fs&d_df8nZZG-5n_jn;^+RZ`viR1Xi8YzhCI~F#QwCLMNiZ0)AG_&9ISwdnWFs6rsoI@3e;`47S zll<+LG#wo`e_WZ^4c{71ijKZN{7x+QX|g2t1#;G+?Maw=_|FtFAs8|_G(@@Nslv78RiLIQ!*+ExM_j9#{V}l)bmzG7HN*6)J}E*3#{SSNFVD zk{~i8{5VMSa3>~&kz!S*k|!U8VZh&TQQn2~uJN`-NMtxNA+TcJuwu&+WI{Ie7^OVJ z-ynZK^3nQJ2JD&4B>BD!o_6C+ zgutaxWGat+Ys~;!Zs%gh_SgV;1i54a@6LyzDFib_4qErw@7QkkivkfB*iS zjG0-!b8xWyzB;TSFffKeS;F1jo#0c4#^Wami1L=C%T>&k`T4E#Ls!R`BA=2qfvf34 z%(@Y``(+u~?oF%;gN{^GZ7r8iStaE23&~S1WAtxpnHK@0EcFmL*!9FifZNyG1CUnp z4Pxuu8}u^Fr_1CO6ch$tb2@S6t7qms$77Q#P%ccYb8YtU+};pZ$T7#m<8&PG;^^iC zUVQ_yAAVkhZicqB{Pmh-e2|Xssu0qJrg62t%g)LA*;v{f zXUXr@pVPweH%Z@a0>?1mU^byFbki-GH?n$J5sM}Xprnd z+24qb*C|U8Ez&T368JpcX(^4wP9Vv2E+Q-|i_Fl+n9`Z+U}GaTBaD=&`Oa16$Ha0} zRn7IiDT<0mRohiLF&WfM`bn6WXKwZ(RJzBP(o^y$;ShJeV z0-OXvYt?)g-pF*soiCTs*eK{wP`=o`$gL4qdMT<>s!ogiay%Ybph+fiSgdd0rp04Y z%J$JlQ}p}z1u8-DZ{)~x_6DtVnA@oxuPI#p$&AGj;?b$KvXEsyE-< z!`r#9S+(>RJIzyrgCe3Ddcv@+tgPzn_PDUW#nQMNbgtfz3-$r=in(rRP_LMJ?Qh=b zGVc_$Ou_rhF#^H-pG48R9@2|REXvmxyOd3CXED9KRCQK=^ewGG1pE)Lud3kyf*2(|WOo56WqJ%ko{HHc+*ShBF`a0qIH=3_W-4hQFkFGcL znHNhglCuR9{wxl&_S}F1cfZ@%Qm8NzuVkd#^B$NeFWp{{6iDKK&r@Z^c-VB8!~NMm z98^x_$2yF-Z~i~+wvkXM%(uz>e7xHEfn1&S97r`ttXghTYa8k$%MH2)s{NU|(jww- zh+JU>gs`!kxPih376+A$dS}jYFY;4qT{i{W$MHJF_aJ31`C}=9El;gm(pVnl=R zR3-*IWz85Em@HbhogQR?9|FFPTg&UJPs&4|j(@1zBa-!11`0%em$TS-B>*m^|88X? zqIQMA-Sfi}rT7V?o2xS1b`b0p*hWLv;Ai|klFj)dUNqa3P(Brm+9d~cz|A#IR^V=6 z&vGuOdJh$8EYN#6;f_ls$KI4wtjv41u#8^4LJ2KNL|jZP5?E{$I6I3M&^)JOs=W|- zdR@Mo&sB05c7xw=tH6yGnnWe*T6lXMcGKk;)2@C~#& zdLCbcYbf&+;V)R}sg7YoVmAEAf(BY%`KXQ1b1qQH3i8T#3m%tIke#wvHnerTlOS3+ zKR?GH6F&W=hN>`f_{u3>-1GNBOo0DkHrwPJQk7^e4Vm6Foc% zVT|3D0o)OZu186q>m}|sqSY!M7kx`of>kf3(^ZgoKDDg*~xv zOLTw_^dMIqA!+W9%dX(f!9)q|hD(&|Qsu(97+OsgU%y>3b%zs>DN*(PG!<9L{6X2g zkv+gI?@RL?2P@G)q0?b1g$Xt;5v3oS_;=-goC9XrNh8q$KF-0O&b_-*g36g_q$Ta@?Ah&?=u(rFg>>c| zO?H05Rn>~Oh@={qKS>Z4(tVz6Fi1-V#!e`Wt?oxNO9kErJ`4?J=-()l0!3ly=;)hL z^WdbXfrx5$^YPvwMJ1&w8|{q`v&X4TZYQ@Vq8~Lyy{-{jU{;EbuW)ty3QL<_?@ks) zrKhhBy^LFXSi`Y}i8Y7{!LrE7d6AL9JILL@uxXU`Iuhyj{GeQm?M7Ak>z~LO_KQ*; zBg03SMu1pLwuyy>Mb^Xa!CND!7jhXE=#taR*%N(Tiu%KHLLxPpNoQ;KLf2{V{t;bN z5HDlc(3Bq0XPIk?KT#i`?brUOD6+;ZMr>_jnl&u5()ACb5Wp~?Q)X#twtQJm9$TmS zw=D;I?;6Mi1Y>MTJc1=9fKGB(H}xKW4u=34kzj{^Kt=+f6Qy~AFONV59bEdJsvPAJ z$S6X9Oh}U7KOiFlE=3@p{0C%c0FY6%v157!GVdWkCZm(*@fk7@AVXt`@(-;cfJ;eZ z)E;_6tTi7%Fqy8ww#Nn#yat#0W9&jcE-@fo=gw1&+I z{|~MCgGo$INa)K!<8!t7t z;!;8K&-K8A#VrLBWF1M6Jxj-MzEFpH>w?&qjC}V7vTbkYGk3fNkJo6EP%YC=s7+Q*BE+_;C<~WCE{~B3VyfK-U{@g zs~aNE7<{Wn;Sl(zChCE_;@~@^Gof4OUqP4u9NbN7J(xx((H*#vAju@j)~c)MW|=#k zGP$}9b-^Ga`YStlvccv5qSQ+f1C#M1k@$=wbh(V2Bo>`IWMHOKp;-rS#1JhLLw)kp zrW{P-Nn4SX?=f6c?YcV`Pb+;bCtEF(Z}@jHt8 zll#>%9s?c*)$(NJGgz3CAK-|tkh~1}d|T1&(Yi|MAQBQ1j>c8<7QF!A|9!s1u{mumLe^1H_O=Hzggq!#`LJ^b;}iS?>$DFwKccL%l!!W zZKYI-bw1@_;N#LF;m}8gCW=m%d${FmH{=v))qz~_T#h*Mwu-E?bM0-Tdq6TU4W0dA zNe@ajzAm_(_o7P1C0?q)W2XRvF!A3*a$~u`#hQS}T}>thC7z>LQ{2z>Y<urIn!wT z>8ZcU;#ykLeN-5}SA33iqL?c7a40UrvsD!|E1ZYn{v0;s%LZ)C6uXCO|7T=;J4JlHH_-hGYg=;DI2 z=k;?jjz6bTvWwPE7m*>@G`-&UcV7yTeJ^%7mn8h2o`pI1zH4i9kQ#mZV?_f=L2@^7 zu}KO8;T+`HR8feyNkEz?vg}U(9oti60zJuDZ~VhtW5Ky1ZZ%D@z29!qR%;k<|CVL_ zuw0;^PvoquL;i*G%>&=-Mw%GB96Ote%5dreI3J}BO#RGu^_PlzkhR|jMmoJW2$QPA zVxmD+){wq+-|<+f)~0&!=329E?ObyMgm>clOX;g{yD)If)M{92d$NU+sFrM!3D%9i z&(IaB6#vR_c)y6H*6hZ4BH~t6tW!->Fc*TY>dOTb&Z87kdCR2-B7AEB7@j;Leetv( zFe&y5)yjSIBg*AQ-q*1hvvw8~Y&-LcI3}LRJFuJ)%aoNwMMbe2+SClf1^FGgKK~Yu zMd=sv7mPkEYX~}}n{;d-stl-Mm(>!J1!1~u zyO~Vk8Yo$Bt23~E(I=UA#M#aLMdt%mBG?C?-mzQ@6 zcV$%%3WC`}TT1IM`wF`Jx(IF}$I-B`j5=v##sF@VDHV~32Ot>mfy>o z_7erFvMdqD&mS8LtI$cw_|vnpvnBM7gd9kpnql;K&T+RF2iX}t^lQ6Fdas&{S~|#y zkSE>Gl5C8#Z{;Fl1kZQz9e`#Q#*epV4Lx6c!L_kYEU*Fp_9(y^+c_OU^&rmnEQ$VYj69a-a zxu}WbK6AVk*3mY3vrn5k3(I;}$Awk{2}g+^(d{@WJfyJkvA)3LF0CFmbN#Xyrf<(+5{AgNFL7M6n0wgRix}nF)bHpJWWxYrw~k#2guVO&zgPFD~|V zOXQXDgiko*DAXL4F?#Cc>n!N4(Y)>Bp(|bHsV*+Sa9sAbL7r4%e(O`#D)Iz3SrfR& zobiR55jjZHJyStj)uEY0W|c@_2aY`1Wif#2o{bIqN;zAN40 zZ9Qyv&sEvu@=A(ENLaj^-J-q);+Dj1Y-$^tkFDH951`4%iy|_Xt8TnFkW1DwB(^Co ziK9sJ0Wry4BGkT3UjFWT(=UAK+rT9=dff7c}&JG@kQABmr6NO<+VfxpN07yNCb5Q9!`u|Iy(c zdiXyfbkHG+Uz@7*WkMgZ^vE@o{uA=kPKC1qGKScP z1Tbz&MvU~b4@mVHBe=~TT$nWXWioBdAL+6D55J|DRvQ1%31Isn- zJ@FU=Jfj61``G3g<@!SIq@>cNi;bO=RLbb+Xy@3Nc1crn>KD((SZC*v-?T-#JVQy4 zv3DQrE!nv}hsV1vHm!biauHR9#U4yR6)?Qanwpwq)+6!06i^fjD!M~-b547aht0YqsQlJxu(0cCUEr*^Tm=wU;&IrE z#pU9HDLasQQupmWVsXzy+y$57EjbVY>#)`KOvFZU;wm>@{zdU_$@l2w7#ds*WqX#` zEsAF1yQe5$Ge}FKo9~`V%%P+hx29*X7X*QvahtL?+tibBt&(lklEMgZlCekQ-rYz>2aCn^djN-=W|$8isQ(9sGdi<`4@y$G zzpuaNjVPi@q=u+hsJcmlRnt|XR;{(X={`?Y$4*gWQ_E88HYdl> zCmrqt z+OclFF4)kkN1dT|IIVND%Y!GlBA&0(l$ab55#Kzem02oqd>hKx-@|GmG54c*V^2NI z?@Ib>WJ(5$)qy#wOsP~NT`&y_8ZyFi^WDwHV9nCkLmW?9aC{Y3(4ch90t30PZ*!VSlwp>DQmpI?YlJE3OS^;mkCV?Bq;kwNigCF@wXxVi%iSdwbD4HY(Na$OP^i zi*%Y)9CrxNDE&slU)jY!n*}s}eeA&9EfV#s7gTQc^Aoh593tz*abr>0fP$I? zL7MFR^(N2=Fu6vznGr7}4Z}206mw*vxhqX1T0Y$*PLFt?3Xt_rR6J9H7HYfMEY{oz z6h+E19iy^gj8KySBHf^PG&@9tvif$f!n>#9T85ta_v=(g_9vLaAFYe4+tfq@a-`=KilXiU8r5tYh^L-%Y zEPpU%>tOTs)=*d9!rum2%X*s_sTY6q@C*+C=ae<26V0H_Ge^g4=M4d{k=~&QwPdeh zwi2U~DVhS|B;)U^joRn5v-JCIfq*hZ+}XS9w39d9e|zIbi7q&RYyw|}I6qi)W zw5sT21X7;+$TQ6zf#{VSW-HUUvW&9a)_)@X1K;=7mOIUAd6vb2^6Tif_DZY3eIO7Q zzbMfTV_LBT+Ki33Br65apFiGrGUO>wRlav3mC92rFcQb(zvh^!2Zo=BB%A)L*(cL@ zFAHGYroSMD9<9lm^!b!Msc;+C;dY>zA76W5yO+&iTy*#UZVVg=?fZUvU9qy&p-^JW z?BXiHnZHz21pD+V3n{w(Smsq2Hp19}1-cn|mZq``A5U@Y@)iqDbNzJ>y)YOKCWd3`n&3pgYh08iwIb z6#`wH<<}Lix1=C){#;(RB;W(0@6jOSbIt6xa){Vwvi(e~KfiQMNPh%pW>8Td*&LZ6 zQ_Q}7en(=*q&!S7zcie}8-LJudJ#GL^lS*CObG94#1T0U7%G_O_ZQKyWi6!T#y@`=KKbSGZG4G!(o1JZ0 ztD`O?K3bX7v}9qdolFG=WLvt<;!n>Hb8V{Zg+)W0!P!<_Z-!lJ&QW)f$a#1)K>cdQ z&DbIO^1YS(1Jpu8tR1k0d0x9c)I*Nvb8WF9pRZP2i=Gn{ zeRO=>f<}RWX25bTVzgh`f&k7N`bF1BCY)^g;WxvT>CEu)Xkm1ikeUf1j(y{vWJO3| ztU2?3N5s0ZbmDZSQz@t&oK&MQW|u_q^>Ivq*TH66D}8@qdHnklvBGx3Yz@Z!&q@z0 z(ALm=J9tedoM_MNcA#}-H>Qh`88--uVvOGR%6!Z7g@?Xg?JqT&eNTipm2N!$+T(so zcj_ln;(R$s@LcWeS{dzBZQG{QBeM>XiknRpWFx-d-#GteX#C9t{s0LndblNl@?zet zg~G6NE{)i~md@OY_iOZTK1W2x>$oUezTj3sV?7>KvWk&-nJc1_>LJ|cVmkQ! zO}=JLNzv5!pOvWvV!zKQQ?;X}E+=QIVV_W1p2-(dbe}Sj9GxeXesXnYt=mog`xBXS ziA1?j`D@0Tr%7M958tgKg=vPx z*0;62PNbTXyeP3UfWih^fSR8#J>`1<1h@RdF7{Z3AiVnbYTwf=K5BjT{T zm7eZ?;$lIE*+7b%*s)559Mby-?p20l83zNyz+DL$pPi*VI4|$x+UjvROWUzN32KBE z3GY2$HjFiOxc_th&eT4oKk+F^?W_cqX(AG~1ybsKV!rtCKbBJT@l`PB@cWBD`>F3& zzHDn3mO}XEqLzMyhXZfG78l?@tn$;0$kXFBJNZOsS&{2Zn9I5Omv5SSdd#eh>}N63|A+itn5!5#x|YXUb9Ss)mL=@wa?Fq|$McZ$>TfG0FHgqbXK)mv0U^K@h$* z4zxcP(9CzKdQ}m#+2`V&N8zm$ssH9uVez?(Ow~ES$UkWOvt~2%40DH+!mo=X7e>Au z$FfjI<)+9mFO-g}aJpvD?AMT)?(z~dZ6Rvo2hN<3fbI2{E)ANHMs*oTqqrF)B0=WWlYnSYtds<{bQa z&Q>c8c_f(}F-R&r>oi^_dkhoyKwP(HYW;x!#nOd99s@h5zf~OaNGQZ<%yh1qvE_#) zHd4q3Xh3Mt;(ekY9*I##DP&WT+h+050v{M*5Cal3JfVD$0R7L4{{QMx*&EcMc^PSG z>_%HnK7MVEjd_{aGf05#4SNja7PNQ3O=o?+&Mqo0E^gNpYZ=j{GmgLj@t8 zqPu&evx`e`O^s8DnDD^JB*65x73opY(d0BV6057LUBkn&z7nwF-amep9#82eb&d5a z0$E>_?wj@crMsIBGCn>na0)x4rKM$^Wm^1GxAOzmd0>W{WM#P8O#yZ}P;y8QWE>SX zYgP(Cc9gGMYN?YmzyTS+0Hb#zlB^x1-dM+1_ih^50Qs|0+}{cb+%l@8v!mFU7%Wy5 z0K2n|LvdDDR*uqiLx3A9KDvD@7dbh(xLB`DzIN^pEY#<0TTZL%;xmN?znVQ7+%ZE2 zh$Dyu83Iv>u!9smV>{l5_xc8eZhYQ-CvmnjL1uqp2~;dkyQo{dD|Iof(IKC~Gv$+! zQIx$zqEJenn_8#K+gN-5d8@N-8Pfni39Kzra7%R!+S!&n#L*!rr$cM4+*(U z%iVpTb76z^^hjHG6f_HP(66y12Zt6+b@42i`OcwQma={rE{Kf%+80aP|I4r^%Ph8F zb$6E(9)%#LqF#`LLnWMm-()@rRGqRM&S*ace$2rNPKs)33C^z0;ugh3STW2TjsQz@ zgVM(OO!sU{YeGZ>gx(Tfki7Zw?Y)^s!FYkPNk@g_jr;hh1yCS;M=X(pZ2dfnFAHD@7UMEnpQl0Yt_*mrs0)< z{-pLbIKP<~n3GL){m7y4>+Ibe)HJ&Mlab@OiBfJotXn1rGa(u{#bFVjn3!V|7Zo3j zStJThTUiDKfov9PgD11n@Y-XC?cl|7lOU}H48M^ z>?VFNZ8Nn;PI$Z~Rp{Tc`#mSG;1bJi7P$hS_Ho|Y`vXc`N|Z+9e%yIZINAxPc5lV?RrnP0uaM5gpb+LT3#3Fwltsax`m;SkLAkt zPt7j&%)KA3i7{V7H=xThaOEeKK{Kp9I~Z~CgGT}^+Al!)bs{>Ap;6I&p082;$>dj45?SGI zZMQ*og$&>G{JEtam9FkgnK=8 z%0-InBv{mN9Z($xh3y6Z8l=WdHM7RMI_wtI#>CCo3C5@LH%MN!(39@J8_MT8+aJ^P zosjUuX3-qh-vx%vI@^<~CQb>)7W&Vbgv2MpEo(iq%1a<>t4XVAs;Mvn{kJq4#SP!m zh7<}G`YSTk7Lw*Ey$=_(#|q_`Za3`L1i&4^PQ=}m)t!B z#II?d*Xs2;3o{6>=A&yrlYT~K7iXoEO^H&k6s$p{+Kh2ooQ6z4rx8_Su}`vNU97b-gdhZa(hn1-l)SkAK{-k>DqEx4>|KI2 zK}i=-bmY&`C={25nq?C*hu*b4frl#rnbu21y*8i`N!8b?3JVR5PDrpD{Vr-pDm5K= zMKT$+V5hI*8*~=VftGoUP4nV{MBt4%u_fXb<{$Y`nxBGLPRjV!Wfe5&TfzjTj>Yyq zC^WCgJQHV8LlNL$bjuCkusiflW)>Et7xD+mgz2f&qR|8gGK0JCiKVE}6cMa_H5{#P zMDvuNI`(e9&ClDC%ax($zrZ^A1__9@@F3Z>_1(2h25#N3?c{-@z7$z8ChFevSa-JU zg?mc^lC8`;Z5p-S1*M7#PX?f#ftxq;J4cfULesJobL(zT{*L-86W1v5H3gh-c?H@p z9D}Fm?N`&do$VEPi_IFJEf}>=_mPHZ?S9r$j!|M`-keB`UE=y*M3vp~J0+M>U86W9 z-(3maw&BECFo%^3|DjtEx5}y<_2A+xlaNREU7o=;(x&+BURkf2=NNi4ml5RL=~R}g&Nfr12@@O@TD6rr3x ztL_b#Y%*7dO#*fz+fmX)z&@dhXy)fIqrt@L3RX6yKaHcZi3w=fc(DNs(TjA%#CI9% z(n3rt~!HJjV`yHj`ts++rcdo)(A1W!_iLanUKE)1fJ*NQ3d}o=<^J=Xp zyMH~QJLBB!dpAoM=Y%3Bk$;bw)v!uZfZ;=AelBui8IzZ9b6kNd%&bN+m$ z507H@Jlo&pBi5V>29$x6wXix|s0m(J4KY1`Ax0jaMOo0O{jaySa1w=a^bWfCmB_Da zE!VBF2ON(5ObYdV=rwbyLge1q@tp{&Ivr#oIffMJoD`~;`LVM%W}j~*iRKW`8t4G~ zO6G4?Ju(EG!_Ke2X4-EnfeBd#5l{UfO^f4V`5$IDdB zbE}K_wDT^zWAe$zvH_&lghWL1*0R@MN15s5Yc{(Yt*iz{8|J&D7m;(8gbaC+dVa1q0QfVP1i##k~Mb>L6nuDB-=0RmX0=f+4!u`olSx@2UDn_Bc}iNwaVcp!f#doT4AJ!~g%0|2J3C%X9!tng84e z#bo#F#Nj0-pxWEB!oiND{j#*X{027nK_TH!?!pHWl?U<_9uX0Zso{Y1u0{nQ_}PXB zzGx-se)<%tRIJ04ZFaX=IyRMGtdr3F< z8<6D&SAWGz=qevd4taC3^>{l(Z|`=lY$u#ws#ywI3vM|}j!!e!NVc@R4b6|!^@KY~^*TaK|->AQ#Y#_Vy}D1B4*uGW4E6BC>-CPGR~H zb9r|lfh_s;G7r)z+v|38A_0qxow;(D3Mr=P#HY{sk@+Ea(kov%UW=lw>)XmnjazPu zSn*vFI-KoIGu%r(t?4sjB0i@QtetsXP~AdCmm~6kE4XZ2m&c zK{_w-a8$kAcqe|C&r`RYpO#h}|HK81+Z%8jaI?yFv9ghSym5k#h4pqGn|pO*ch%Ct zyhvBJkC%fEObDF5?IRK5Gr2Rrk_J;QEd6ab#%r}vr%DdF?L_>{Q+~6Ud*nDRE}?k; zTNX#NtaIEpYcyR*xe&)b(WmLi<1enSRcVN^RdG1DK{RxAq-aDvCo{CDHh4Nfw=pj@ zF%S9K_8##zOpgWoJQ zEj!!U)~24pINY-wgYwbFy>aNVRXG9S-q-j2_aiTPZzM=>C(t-#fkENC&w+ zj!GIuF^#X?OUOAn=`=4+fE*v&ih`*QELC%C8l4;W_&0pZ+&bP56A?uf1G&g98wdWk zmj&wAZ{~kS?xFUIr2(Etog=d!n4J>aY~T%F{PRXUnj&dX-t8UO&{%eQt)5Mg6i zPs>=-l*HG8=z;VN{EYsDL76b&$^%<44 z19X$GYe5ajyXG)Qx41}WJ>O{hbeG-zpORf6$abd;3-#2pem0P6bM?3R5t30IS(6IN zTJ4iIxhit^>%hL0s~RHIdb)<|-+#W${w0Q&Iidx*w_rbRZ%bJBLBR~+q6ZNV6&wLP@d9Vp!DV3nRN->w zoDYTbRX;2f%t0)3nEuw*Bomjv8qBgz)RJ=7Uyn8KdR1eWhzyVN>TO5&{9T>9KbHN& z;_4=&y^D5}{9~;!k^U#uxuM|@a=h3#DR_ zb(=u*ZHV#nJ*Vm-w^OqJlN-!Gyh%P7j=EQ;I_C<8$vd5w{H$Bo`7&JZH{;SPmlb-V zP*-WW65&r4?N3fp?0D!XedBU6CjHu!vACa}0Gs$Nt3g2B;q?AXs?jXDxNL_<{wH=v zmQ^x9m?-J#uoAT2;0iHXH=Q*KWCc5|`P7*ti9~gV^e3JA`Sl3i)#++%FF7~V#+>fs zMh!cL#^}48c`S!;zc7Dtqg<#W_5+*f72wyzgg%Pntv%-J5({opTy*41=aFy| z#SZpt4Od48O?o0TWmZSSAR|J-JtM}w)b^%1PqN89wCFj6pl`_YD=_jupCoYNm)T`M z$?jVZDWxz0MA_R{SZsX1d@kpraWm}JG3X~!|bU@;+ zF@dF;5BI!FU63uQvzYp_E1Q&*X6c z_yHTDm(foMw`Hwtl8wZ4qdN&zMm#Ek#4|J7Mj(uRm3Vhf<1rodPo~7`xafUF`~KYlHK5j&-R-_jf&_n)4pgqmoseJ*4fg! zpuXgEYuJUW49H^1h|^%lBxH^SW}!sCqsF^grt~5O#~3c_Iav?wDjlY{<6>;aU=jLO za}RZ9kiOR%&h9+YI|9;Jr4)Oq?bNStaJOCse+V{Bs-flSdWUq`gG(=oM@Rh_Imi6T zl%I{%BA?o7JO)|8HV}noYr5FE*|GB9I!4&JLZ#l!%)mG~#8TUg?6K2Okeg>Pze-zMYET+CY z8kXsKc<6pKu}^$i9#nC1QgxImQuhshelF3Uc5hmmyhUO+-+OsuRZRlh1xCJ*OzkEQ zZK;nqhI{pG?LxSuyatS%)yAo?eauEjM(PD=MCPY-*OsKC>q+3#BnC-Wvs3$VnoSERyp;tHSI#m8^;<4QIR9{_)Uisum_}(qZ{23iyP-|RIfroL}2Q3%xE*WYmG|^pnRiILlV7b`FR&A?? z^6M8w%`NO_Dn)LBjZX(ey0H8)_EsWW`U!J`*wI>6(TPG-mTC{>Y9K%@$PATL#?BL! zea3hF+wt4Y3JjQ1@W>CG;G3o)#(vv@=UNx==Y2IIukl+xrClhwa58FpQvwI!hgcpRmjzAw^lx<-XqnfZVEk~~w(e!c!Sv|6_?g5RpH z->vetMw+P))Utl z+WU0hemKLQkM`DnrXurY>NM;&bxGSrF~u8clXz-Qe+^)pl`aglY2D|R(%5kcsB zR<*K=#oXosr>{$chn>7)?NR|6tRnaa_rsZb$QI|yGHy1s&itha!rYusuYmm8;HjNY zJg3!|q)_r=TZ~bx4&Ar5>d+NOH!$oCz;Uz{!*8n}h%9Y~cs!0h?MYY4qw0OJj+8CclV?@$I!A z7X#5$;yI4sMPGTRLk-w1byjG~2<3A#QF3tW&7OYnKwz1@LIO zdEVAY5$Ca{H(v_nmezpwWa3~+fy$R8%-@mPrR^CaSKrEn$-O5l%&T%S*pja<;(nlX zf;7U&K&t)(!LFBGNl$t;O21}4X}9k({FZJ50qF={y^M6*Z<)MZ)_YFi$5*rM0462y zAg0%q{ivF%{Mrunp)x3_sqnxHHUlVOFvZuJ7k*bKChP2L}^N|Dc zQ3MXo85YK^Q$(rBO`7A*WQ!W!tjjUip)ZWn#;Qs9myXXw7vc{ezs{}RopaaJ#5r_R z(TKnQMVe;>SH&SNQ z0JmLB67wtUsUj`bE9L}28HhP&AWG~2&a!^Y6d=R$KG`JK~w8tSq4<{`T=KwQ2V z7>K}hS$3x@Vv3ufEc52Fv^>?JPo}l$WfdTY)updunKYS4P2FDEkX+_ElyTU{b^hI} z?u!Xz(|1-Qz!5T4#*3@*80-J)P?bWP&Llpok=fgfFWZ#Gqbopv@Jnc>LBGw~Ww#;2 zGI0Wtkk)|nwSo|v&fZIY`P!46^ro$kqXGE%=4%7Dvep623K9M>yo){AoFvCLP1e67 zPi+075)Ov@sWW~lv==YvyyP*e9)rE0En|vU3*D#1Xta*iBuE7pr1Q0*a>*jWZXs?e zRogQdCL5#L*K?1n^Yh-sgc)|w3-5DQEl_I_i1Z>sNg{a}wlRH4!kP>xzi(7mg@@xA zws9++;b^hhOfM7>y_>(L2Sks7$B*vb={Bx*zjmWd!TO>xODzo(*;~asw9%i5?JA4= zA<-*J&@!iRWOKp%1zdtg&ug{>e#L?^jZY4qzLzI*SSYCxVwEQS#cMSY%*p)bzXZfM z<_yL=hDX#;tL>~|m4%iq)1c=-i%<{+8v4*@UtG-*Fc)gUI6{160!GGI8^4N)45WOE zsWRn4VaKS?db{PGT|U)Iak|uN7C$LIB0)Xr6jInRD^`hHwOKzE?2bm24*s2NCFMrE zIkhYAoGhhk&+wn_3Rz%otLQ-d9Mg2X_c9i}Q`Dvrkem~ghPj1G<_N)pWjlIY?OXK` zTKX}NvCDt8mj3GDb>?}Oq2bA&RG&(hoVWbr&0qKL7^LTEw4CN@Yx>ysqqF0CY0EQ} zu|{_@xvg~q`c9kvG`$wl(<%A>xwexZ{39MXD)UYfvRDK}$ove9!Ld%9{D3IXD6}~ zCQT<)G$ok+J|OKNC&eehGyEPtNm#uG#B*ViAquxt?j;2WG8&BLy>^78>HbV^RE>IT zTPNQ81M!xcg(P{uRCd^l-+}wI1|MUCpSla%C`cr6ahsKNFTQEUCiygOn;y>V@dX00 zifZoGiY+X_BZlHrie1N56(4>m~QA5VDbd=(JNV(ZY+X-5%hVyM{NBh1~$^ z$%q;h>bC?1)V^7Vuzp$IYOu`_j{8t$H&6U2voll4+@H7{AAKbfA(Esqi9_?C{;7uv z2HPL;%MI@aSI#)?GCol3XGW_QPx^r(Q+Sz44Igt3LFeJpRFl)WOr88ZRG)NyUSsqx zR4%$A2D-oc|AGR?0;Kru71I2oH7?bM*E7eT}YVKq$ zr9=CG;gbFzU}Df9GF?W)ZA3G?gdC zGC7c?o*Lwm=u~!*3fk;U+Sc55CdRZ0NhFq#-QRbUXi7OB-t9Hrd8pUg=UVFOPrhbd zI-a{yTut*Qk4oUo>qR=dQTTyP$_R!WMrm5rDS`&XVHo4+$jEJJX!>)Z6gI^a=RH4* ze13Kn4UIg2@EcG2r=zmQ*45QrU!}YxjW_{!bP&EbaM}Dl-W)XsQ!C)hVGx1@#Un;E z4nfDgBsVVCP(b1w4ea1DDVf;tA~b8OkC51!d`>*>4QBpp9ue0&DJ15E(?^#E$Yl3E1hWIXUI7 z-P}14d^?8nj4`Jh%S{LWey2-~Eh+IeldDGW8wW@o_3Ga&%;3V`R(gjXdl!U8qiam` ztU8|HZy>M{e+FUo9DqHn=fiK!iU&2S`ykl$FFPnIo;`a6isk|gzNZLdOrS*@) zG>-FGA@_=5A<0WEOF8>@qYKeASO|H@bog*2UjDb-(u@@b%K?Sbc z)4CZUmx4c*qtf@NQBoL$xenGkmId`qjQMqjvugr{M4oCFTDc{YKHK zFP^OoWaIVuV~(vO>htQCdTs@F0Y0yUQLS3dL*ulZI)|ai<-`oWaC0V=Iwxp+6^f@` z`nAICt!2N!ckjq;F=+u?Hn@)cCOW^5Pu*Di+U=UXikx8UR`RbyN2C&A(d>G9lG0}7N-lE zLyo(Y+c4|5Drzn__WJ7Av$&usL^mjO6OEBqrNMn-bZr>ctvDz^cc1a30ohh!O*e*D z6;I9tgJ>sC?VWjYT970Us1$PJIo0_W!JC0y>|E)C;_9E5#zJ!`UPoUl7rv1jiKhW zI^db%@NV!$Z&}eZW<7Z++%J(P1(h0{quSp;`|~P~29xGN-Jrd;{nhy(M&}9bwwjF% zDM$7Ohv~}qfozwGJdg^7zI~ACI9~NEq`2YNtC@6H)rzss>Cl*u+gtBKhAF)bTYSXC z`y^&Uot=u1jTHZP(ACbvrL_R>xg4On6DD-9ymfB1a|6^`|Q&;6}y<2y(M=) zgYc2@e*d@-7Zr!bM{r7L8Yg2I7&wNJq(iwNJ=@mxG+{#U@F(PG@c3cJ?jhjUfbBJy z*)l7#HR+o4Cs8Kzo049Yo%CXZEfvELuLjnBsNLq{CJLn2cx)gJRv}UB`JO<#yWS>6 z*3r1CF3FkBeJx6-p;o*kd>nPCG2!rW)x=0@Ec7yV6`9htlvN}_v#!&?ZVI~^kP;0kuT?`}$!jd%eQpgQH@j$8> zq7)-nPc^M0xOGz*?^`zl{D)$81E2w_VI70~_%ZR>($i&f4k?=M5C7TlAK`hK_LRkA z1heYTp|pO5k3RdHAs+_YsR8Y=&ICzG*$=(c@*ET3SqMsdJNQP$a!zm}^(w1|Xr)K! zxDY0}1TC5dm(vfLbp2>J-?1mU7>JQ-@6!DHks2hALdX0XrC0ybUg0oTaO-+1moKNp z?t7{kY^4VC(n*GT;hj$0n&hH=+Z~nwi4hbmpH-6GrKIGZKtd=fJN-+8%n77eem~eL$Qx(V~wZGMm?n7WRKcwY}7AfEc3z{aUV@iVij5?oRXJdZ>_L zv-}GITUNmV63Lo9#+V;;vj~OO2|sZ;5AiW~DpIs)mBea0vl@kCU{me+z0vjn9u|54Q}`p1P@NsL1mMZdXsnFzU$KZ85Di^ z_ncF{aG>J5M;*>!2L(PnVZtiF%3vTrAkrN1uz$xu0$X(bYUw1Z`!8tegPp(XB+B~c ze>{`^y)6PuHPG%JD)MIdiO{i$QMVwVeJ>hbV}Y;wEz;YD-m3%~KOir(^$C-*|4R$- z^Y+>$eD&Tj3v#aXg0`Rc0Uvs1iTEce==5ZD>RuiQr%@kxu4*c2%8ty5A%H(AF?rFV I_j*463lNexng9R* diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index 439915b7a42..99070222bd1 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -28,11 +28,6 @@ ibexa: preview_url: 'https://frontend.example.com/page-builder-preview' # The front-end URL loaded by the Page Builder's iframe ``` -Then, edit the content types with Landing page field type that are used headless, -edit that field, and check the option "Edit in the headless Page Builder". - -![Checked "Edit in the headless Page Builder"](headless-page-field-edit.png) - ## Configuration (SaaS) TODO: Saas only, remove from on-premise documentation From 26feea75f9098985ddb38eb98da28ca14259a7b3 Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Tue, 6 Oct 2026 16:37:59 +0200 Subject: [PATCH 24/31] Headless Page Builder: rm "Edit in the headless Page Builder" checkbox Co-authored-by: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> --- docs/content_management/pages/headless_page_builder.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index 99070222bd1..8912d093d13 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -10,8 +10,6 @@ The Page Builder can preview pages hosted outside the DXP. You provide a single URL for the front-end page and let it communicate with the Page Builder using the JavaScript message API. -The usage of this front-end page instead of the DXP one is set per content type. TODO: This is on-prem only, SaaS don't have the choice - ## Configuration (on-prem) TODO: on-premise only, remove from SaaS documentation From a611c863c67d57da2a8f4dab77cec36fbb622904 Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Wed, 7 Oct 2026 12:39:17 +0200 Subject: [PATCH 25/31] headless_page_builder.md: Rewording Apply rewording done while working on SaaS version #3437 --- .../pages/headless_page_builder.md | 177 +++++++++--------- 1 file changed, 88 insertions(+), 89 deletions(-) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index 8912d093d13..c1f5137a698 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -1,14 +1,14 @@ --- -description: The Page Builder can preview pages outside the DXP. +description: Preview and edit in Page Builder using your frontend. edition: experience month_change: true --- -# Headless front-end preview in Page Builder +# Headless frontend preview in Page Builder -The Page Builder can preview pages hosted outside the DXP. +The Page Builder can preview landing pages rendered by your frontend application. -You provide a single URL for the front-end page and let it communicate with the Page Builder using the JavaScript message API. +You provide a single URL for the frontend page and let it communicate with the Page Builder using the JavaScript message API. ## Configuration (on-prem) @@ -28,11 +28,9 @@ ibexa: ## Configuration (SaaS) -TODO: Saas only, remove from on-premise documentation - -Navigate to **Administration** > **SiteAccess Configuration** > **Headless** (`/siteaccess-config/default/headless`) - -TODO: Should `admin` SiteAccess be picked instead of staying on `default`? (`/siteaccess-config/admin/headless`) +- Navigate to **Administration** > **SiteAccess Configuration** +- Choose the SiteAccess for which you want to set up a preview. Choose none to set up a default preview for SiteAccesses that do not have a specific preview. +- Then, click **Headless** Below the description, enable the **Headless mode**, fill in the **Page Builder preview URL**, and **Save** the configuration. @@ -40,14 +38,14 @@ Below the description, enable the **Headless mode**, fill in the **Page Builder ## Communication protocol -The front-end resource targeted by `base_url` is loaded by the Page Builder when editing a content having a Landing page field "Edit in the headless Page Builder" enabled. -This resource must follow a protocol to communicate with the Page Builder from the iframe is loaded in. +The specified frontend resource is loaded by the Page Builder when you edit content with a Landing page field. +This resource must follow a protocol to communicate with the Page Builder from within the iframe in which it's loaded. This protocol is based on the JavaScript message API. -The Page Builder sends messages to the framed front-end resource. -They can be received by listening the [message event](https://developer.mozilla.org/en-US/docs/Web/API/EventSource/message_event). +The Page Builder sends messages to the frontend resource in the iframe. +You can receive them by listening for the [message event](https://developer.mozilla.org/en-US/docs/Web/API/Window/message_event). -The front-end resource sends back messages to the Page Builder. +The frontend resource sends back messages to the Page Builder. They can be sent using the [`postMessage()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) method. The target origin of those messages must be the Page Builder's origin. @@ -56,7 +54,7 @@ const pbOrigin = 'https://admin.example.com/'; window.parent.postMessage(message, pbOrigin); ``` -Those messages are JS objects with the following structure: +These messages are JavaScript objects with the following structure: ```js let message = { @@ -65,24 +63,26 @@ let message = { }; ``` -The `PREFIX` sort message types by their sender. -`PB:` for messages sent by the Page Builder, `APP:` for messages sent by the front-end resource. +The `PREFIX` identifies the sender of each message type: + +- `PB:` for messages sent by the Page Builder +- `APP:` for messages sent by the frontend resource The data depends on the message type. -Message types are then sorted by capabilities. -So the front-end can declare which capabilities it supports and the Page Builder can refrain from sending or expecting unsupported messages. +Message types are also grouped by capability. +The frontend can declare which capabilities it supports, so the Page Builder can avoid sending or expecting unsupported messages. ### Message types and capabilities -The handshake and core messages are mandatory and not related to an optional capability. +Handshake and core messages are mandatory and don't depend on optional capabilities. | Capability | Message type | Description | |--------------------|---------------------------------------------------------------------------------------------|--------------------------------------| | (handshake) | [`APP:INITIALIZED`](#communication-initialization) | Establish protocol and capabilities. | | (handshake) | [`PB:INIT_MODE`](#communication-initialization) | Confirm protocol and draft info. | | (core) | [`PB:UPDATE_FIELD_DATA`](#on-field-update) | Send updated field data. | -| (core) | [`PB:DISPATCH_EVENT`](#re-dispatching-events) | Re-dispatch a front-end event. | +| (core) | [`PB:DISPATCH_EVENT`](#re-dispatching-events) | Re-dispatch a frontend event. | | `blocks.dnd` | [`PB:DRAG_START_PREVIEW`](#drag-and-drop-blocksdnd) | Existing block drag started. | | `blocks.dnd` | [`PB:DRAG_OVER`](#drag-and-drop-blocksdnd) | Mouse position during drag. | | `blocks.dnd` | [`PB:DRAG_END_PREVIEW`](#drag-and-drop-blocksdnd) | Existing block drag ended. | @@ -95,13 +95,13 @@ The handshake and core messages are mandatory and not related to an optional cap | `blocks.remove` | [`APP:BLOCK_REMOVE_RESPONSE`](#block-removal-blocksremove) | Confirm removal. | | `blocks.remove` | [`APP:BLOCK_REMOVE_REQUEST`](#block-removal-blocksremove) | Request block removal. | | `blocks.reveal` | [`PB:SCROLL_INTO_BLOCK`](#block-reveal-blocksreveal) | Scroll a block into view. | -| `blocks.select` | `APP:BLOCK_CLICKED` | TODO: Block clicked. | +| `blocks.select` | `APP:BLOCK_CLICKED` | Block clicked. | | `pointer.tracking` | [`APP:MOUSE_POSITION`](#geometry-and-pointer-tracking-blocksgeometry-and-pointertracking) | Report mouse position. | | `preview.params` | [`PB:UPDATE_PREVIEW_PARAMS`](#preview-parameters-update-previewparams) | TODO: Update preview params. | ### Communication initialization -First, the front-end send an initialization message to the Page Builder, indicating which version of the protocol and which capabilities are supported: +First, the frontend sends an initialization message to the Page Builder, indicating which protocol versions and capabilities it supports: ```js const initializedMessage = { @@ -121,17 +121,17 @@ const initializedMessage = { ``` The Page Builder replies with a confirmation message. -The initialization message might be sent several times until the Page Builder replies to it. +The frontend may send the initialization message several times until the Page Builder replies. This confirmation `data` contains: -- the actual version of the protocol used (`protocol.version`) and the other supported versions (`protocol.supported`) +- the protocol version in use (`protocol.version`) and the other supported versions (`protocol.supported`) - a list of all available capabilities (`capabilities`) -- a list of the existing block types, their attributes, and their configuration (`blocksConfig`) - It contains all the block types but mark as not visible the blocks not available for this field. -- information about the actually edited content draft (`intentParameters`) -- the current value of the Landing page field being edited (`fieldValue`) including the layout, zones, and blocks. +- all block types, their attributes, and their configuration (`blocksConfig`) - types unavailable for this field are marked as not visible +- information about the content draft currently being edited (`intentParameters`) +- the current value of the Landing page field being edited (`fieldValue`), including the layout, zones, and blocks - a block-ID-to-name mapping (`blocksIdMap`) -- a list of translations for the front-end to use (`translations`) +- a list of translations for the frontend to use (`translations`) ```json { @@ -233,12 +233,12 @@ This confirmation `data` contains: ### On field update -The `PB:UPDATE_FIELD_DATA` message is sent from the Page Builder to the front-end resource when the Landing page field value is updated. +The `PB:UPDATE_FIELD_DATA` message is sent from the Page Builder to the frontend resource when the Landing page field value is updated. -Its data contains the new value of the field with the following structure: +Its data contains the field's new value, with the following structure: -- Always, the current value of the Landing page field being edited (`fieldValue`) including the layout, zones, and blocks. -
For example, only `fieldValue` is sent when manipulating the [timeline]([[= user_doc =]]/content_management/schedule_publishing/#timeline)![](page_builder_toolbartimelinetoggler.png){style="display:inline;width:27px;vertical-align:middle;"}. +- Always included: the current value of the Landing page field being edited (`fieldValue`), including the layout, zones, and blocks. +
For example, only `fieldValue` is sent when you use the [timeline]([[= user_doc =]]/content_management/schedule_publishing/#timeline)![Timeline toggler icon](page_builder_toolbartimelinetoggler.png){style="display:inline;width:27px;vertical-align:middle;"}. - Optionally, a list of the existing block types, their attributes, and their configuration (`blocksConfig`) - Optionally, a block-ID-to-name mapping (`blocksIdMap`) - Optionally, a list of IDs from the new blocks that have been added (`highlightedBlockIds`) @@ -275,9 +275,9 @@ window.addEventListener('message', (messageEvent) => { #### Available events -- `ibexa-active-block-clicked`: It confirms `APP:BLOCK_CLICKED` have been received. It has no data. -- `ibexa-post-update-blocks-preview`: It's sent when the timeline is used. - - `fieldValue`: The same as in [`PB:UPDATE_FIELD_DATA`](#on-field-update) TODO: Why when timeline move to a revelation time, the block is still invisible here while made visible in PB:UPDATE_FIELD_DATA? +- `ibexa-active-block-clicked`: Confirms that `APP:BLOCK_CLICKED` was received. It has no data. +- `ibexa-post-update-blocks-preview`: Sent when the timeline is used. + - `fieldValue`: The same as in [`PB:UPDATE_FIELD_DATA`](#on-field-update) - `blockIds`: A list of all the block IDs - `blocksMaps`: A map of block config per block ID @@ -290,10 +290,10 @@ window.addEventListener('ibexa-post-update-blocks-preview', (customEvent) => { ### Geometry and pointer tracking (`blocks.geometry` and `pointer.tracking`) -The pointer tracking and the geometry helps the Page Builder to position the block editing menus above the front-end preview. -Such menu is a `.c-pb-headless-preview-menu` element positioned by the Page Builder from its DOM above the preview `iframe`. +Pointer tracking and geometry help the Page Builder position block-editing menus over the frontend preview. +These menus are `.c-pb-headless-preview-menu` elements positioned by the Page Builder in its DOM above the preview `iframe`. -`APP:MOUSE_POSITION` message is sent from the front-end preview to the Page Builder to declare the actual position of the mouse. +The frontend preview sends the `APP:MOUSE_POSITION` message to report the mouse's current position to the Page Builder. ```js window.addEventListener('mousemove', (mouseEvent) => { @@ -307,9 +307,9 @@ window.addEventListener('mousemove', (mouseEvent) => { }); ``` -`APP:POSITIONS_UPDATE` message is sent from the front-end preview to the Page Builder to declare the actual position of the blocks. -Its data contains a list of objects with block IDs, their positions, and dimensions in the front-end preview. -This format is close to [`getBoundingClientRect()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect) method. +The frontend preview sends the `APP:POSITIONS_UPDATE` message to report the blocks' current positions to the Page Builder. +Its data contains a list of objects with block IDs, positions, and dimensions in the frontend preview. +This format is similar to the object returned by the [`getBoundingClientRect()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect) method. ```js const positionsUpdate = () => { @@ -336,11 +336,9 @@ const positionsUpdate = () => { }; ``` -This message should be sent each time the positions of the blocks change. -It should be sent after updating the blocks, like in response to [`PB:UPDATE_FIELD_DATA`](#on-field-update). -It should be sent after scrolling or resizing. +Send this message whenever the positions of the blocks change, for example, after updating the blocks in response to [`PB:UPDATE_FIELD_DATA`](#on-field-update), scrolling, or resizing. -`APP:SCROLL_END` message is sent from the front-end preview to the Page Builder to notify that a scroll operation has ended. +The frontend preview sends the `APP:SCROLL_END` message to notify the Page Builder that a scroll operation has ended. It has no data. ```js @@ -368,15 +366,15 @@ TODO: Is there other events that should trigger a positions update? ### Drag and drop (`blocks.dnd`) -`PB:DRAG_OVER` message is sent from the Page Builder to the front-end preview to give the position of the mouse while a (new or existing) block is dragged. +The Page Builder sends the `PB:DRAG_OVER` message to the frontend preview to report the mouse position while a new or existing block is being dragged. !!! tip "Mouse tracking" - - `APP:MOUSE_POSITION` helps the Page Builder to know where the mouse is when moved over the preview. It's associated to `APP:POSITIONS_UPDATE` to know if a preview block is hovered. - - `PB:DRAG_OVER` helps the front-end to know where the mouse is when a block is dragged over the preview. + - `APP:MOUSE_POSITION` helps the Page Builder track the mouse as it moves over the preview. Together with `APP:POSITIONS_UPDATE`, it lets the Page Builder determine whether the pointer is over a preview block. + - `PB:DRAG_OVER` helps the frontend track the mouse as a block is dragged over the preview. -`PB:DRAG_START_PREVIEW` and `PB:DRAG_END_PREVIEW` are sent at the beginning and at the end of a drag operation on an existing block in the front-end preview. -Its data contains the ID of the block being dragged (`blockId`). +The Page Builder sends `PB:DRAG_START_PREVIEW` and `PB:DRAG_END_PREVIEW` at the beginning and end of a drag operation on an existing block in the frontend preview. +Their data contains the ID of the block being dragged (`blockId`). ```js window.addEventListener('message', (messageEvent) => { @@ -391,17 +389,19 @@ window.addEventListener('message', (messageEvent) => { }); ``` -`PB:DROP` message is sent from the Page Builder to the front-end preview to notify that a block has been dropped. -It has no data. Combined with the last `PB:DRAG_OVER` message, the front-end can determine where the block has been dropped. +The Page Builder sends the `PB:DROP` message to the frontend preview to notify it that a block has been dropped. +The message has no data. Combined with the most recent `PB:DRAG_OVER` message, it lets the frontend determine where the block was dropped. -`APP:DROP_RESPONSE` message is sent from the front-end preview to the Page Builder to tell where the block has been dropped. +The frontend preview sends the `APP:DROP_RESPONSE` message to the Page Builder to report where the block was dropped. Its data contains: - the ID of the zone where the block has been dropped (`zoneId`) -- the ID of a block that is now below the dropped block (`nextBlockId`) if the dropped block isn't the last one of the zone. +- the ID of the block that will follow the dropped block (`nextBlockId`), if the dropped block is not the last block in the zone -In the following example, `targetBlockId` value is the ID of a block the dropped block was dropped on or just before, so the dragged block takes its place and move it below, or `null` when dropped at the bottom of the zone. +In the following example, `targetBlockId` is the ID of the block that the dragged block was dropped on or just before. +The dragged block is inserted in that block's place, moving the existing block down one position. +If the dragged block is dropped at the bottom of the zone, `targetBlockId` is `null`. ```js const dropResponseMessage = { @@ -413,10 +413,10 @@ const dropResponseMessage = { }; ``` -After a drop `APP:DROP_RESPONSE` from the front-end, the next `PB:UPDATE_FIELD_DATA` message from the Page Builder contains the dropped block ID in its `highlightedBlockIds` array (`messageEvent.data.data.highlightedBlockIds`). +After the frontend sends `APP:DROP_RESPONSE`, the next `PB:UPDATE_FIELD_DATA` message from the Page Builder contains the dropped block's ID in its `highlightedBlockIds` array (`messageEvent.data.data.highlightedBlockIds`). -`PB:SCROLL_BY` message is sent from the Page Builder when a block is dragged near a border of the preview which needs to be scrolled. -Its data contains the `top` or `left` amount to scroll by. +The Page Builder sends the `PB:SCROLL_BY` message when a block is dragged near an edge of the preview, indicating that the preview needs to be scrolled. +Its data contains the amount to scroll vertically (`top`) or horizontally (`left`). ```js window.addEventListener('message', (messageEvent) => { @@ -428,12 +428,11 @@ window.addEventListener('message', (messageEvent) => { }); ``` -See [Geometry (`blocks.geometry`)](#geometry-and-pointer-tracking-blocksgeometry-and-pointertracking)'s `APP:SCROLL_END` message to declare the end of the scroll operation -and `APP:POSITIONS_UPDATE` message to update the blocks positions. +For information about reporting the end of a scroll operation and updating block positions, see `APP:SCROLL_END` and `APP:POSITIONS_UPDATE` in [Geometry (`blocks.geometry`)](#geometry-and-pointer-tracking-blocksgeometry-and-pointertracking). ### Block reveal (`blocks.reveal`) -`PB:SCROLL_INTO_BLOCK` is send by the Page Builder to the front-end preview to request that a block is scrolled into view. +The Page Builder sends the `PB:SCROLL_INTO_BLOCK` message to the frontend preview to request that a block be scrolled into view. Its data contains the ID of the block to scroll into view (`blockId`). It can be used with the [`scrollIntoView()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView) method. @@ -441,7 +440,7 @@ It can be used with the [`scrollIntoView()`](https://developer.mozilla.org/en-US window.addEventListener('message', (messageEvent) => { switch (messageEvent.data.type) { case 'PB:SCROLL_INTO_BLOCK': - const blockElementToScrollInto = document.querySelector(`[data-ibexa-block-id="${messageEvent.data.data.blockId}"]`);; + const blockElementToScrollInto = document.querySelector(`[data-ibexa-block-id="${messageEvent.data.data.blockId}"]`); blockElementToScrollInto.scrollIntoView({ behavior: 'smooth', block: 'center' }); break; } @@ -450,19 +449,19 @@ window.addEventListener('message', (messageEvent) => { ### Block removal (`blocks.remove`) -`PB:BLOCK_REMOVE` message is sent from the Page Builder to the front-end preview to notify that a block should be removed, for example, from the Structure view. +The Page Builder sends the `PB:BLOCK_REMOVE` message to the frontend preview to notify it that a block should be removed, for example, from the Structure view. Its data contains the ID of the block to remove (`blockId`). -`APP:BLOCK_REMOVE_RESPONSE` message is sent from the front-end preview to the Page Builder to confirm that the block has been removed as requested by `PB:BLOCK_REMOVE`. +The frontend preview sends the `APP:BLOCK_REMOVE_RESPONSE` message to the Page Builder to confirm that the block has been removed as requested by `PB:BLOCK_REMOVE`. Its data contains the ID of the removed block (`blockId`). -It can be sent immediately or after removal animation. +You can send it immediately or after the removal animation. ```js window.addEventListener('message', (messageEvent) => { switch (messageEvent.data.type) { case 'PB:BLOCK_REMOVE': const blockId = messageEvent.data.data.blockId; - const blockElementToRemove = document.querySelector(`[data-ibexa-block-id="${blockId}"]`);; + const blockElementToRemove = document.querySelector(`[data-ibexa-block-id="${blockId}"]`); if (blockElementToRemove) { blockElementToRemove.addEventListener('animationend', () => { blockElementToRemove.remove(); @@ -481,6 +480,7 @@ window.addEventListener('message', (messageEvent) => { } }); ``` + ```css .c-pb-block-preview--is-removing { animation-duration: 1s; @@ -494,36 +494,35 @@ window.addEventListener('message', (messageEvent) => { } ``` -`APP:BLOCK_REMOVE_REQUEST` message is sent from the front-end preview to the Page Builder to request the removal of a block. +The frontend preview sends the `APP:BLOCK_REMOVE_REQUEST` message to the Page Builder to request that a block be removed. Its data contains the ID of the block to remove (`blockId`). -The Page Builder responses with a `PB:UPDATE_FIELD_DATA`. +The Page Builder responds with a `PB:UPDATE_FIELD_DATA` message. ### Preview parameters update (`preview.params`) `PB:UPDATE_PREVIEW_PARAMS` message is sent from the Page Builder to the front-end preview when TODO: it's sent on several occasions without data. It seems also (if not mainly) used by segmentation. -## Guidelines for front-end implementation +## Guidelines for frontend implementation -The protocol documentation is illustrated with Vanilla JS examples. -You should use a JS framework to implement the front-end. +The protocol documentation uses vanilla JavaScript examples, but you should use a JavaScript framework to implement the frontend. TODO: React, Angular, and Vue front-end kits should be available through npm packages in the future. What about the Next.js used for a demo? -Pure frontend and Page Builder preview should share most code as possible. -It could be a same controller called in a different ways to know which content to render on frontend or if it's framed into a Page Builder preview. +The frontend and Page Builder preview should share as much code as possible. +For example, you could use the same controller, called in different ways, to determine whether to render the regular frontend or the Page Builder preview. Each block type view should be implemented as a component so you can easily add new block types and new views. TODO: Text block type (`richtext`) need a conversion from [RichText DocBook XML](richtextfield.md#custom-docbook-format) to HTML. TODO: You shouldn't implement this conversion fully on your own. Use Ibexa library, extend a DocBook library, use the XSL files, . For more information see [RichText to HTML helpers](#richtext-to-html-conversion) -CSS classes can be named however you wish, but it may be advisable to follow certain conventions to help the reuse of existing style sheets. +You can name CSS classes as you wish, but following these conventions can make existing stylesheets easier to reuse. ### CSS classes and data attribute conventions -Some class names are, by convention, only used when the front-end is used in the Page Builder preview, some are always used. +By convention, some class names are used only in the Page Builder preview, while others are always used. -For example, the convention is that when the front-end is used in the Page Builder preview, the `c-pb-iframe__preview-body` class is added to the document body. +For example, when the frontend is used in the Page Builder preview, the `c-pb-iframe__preview-body` class is added to the document body. #### Zones @@ -533,7 +532,7 @@ The always present `data-ibexa-zone-id` attribute (`zoneElement.dataset.ibexaZon |----------------------------------|---------|-----------------------------------------------------| | `landing-page__zone` | No | Every zone container | | `landing-page__zone--${zone.id}` | No | Each zone container with its own ID | -| `m-page-builder__zone` | Yes | Every zone container when previewed in Page Builder | +| `m-page-builder__zone` | Yes | Every zone container in the Page Builder preview | | `m-page-builder__zone--dragover` | Yes | When a block is dragged over the zone | | `m-page-builder__zone--empty` | Yes | When the zone has no block | @@ -544,7 +543,7 @@ The always present `data-ibexa-block-id` attribute (`blockElement.dataset.ibexaB | Class name | PB only | Description | |---------------------------------------|---------|-------------------------------------------------------------------------------------------------------| | `landing-page__block` | No | Every block container | -| `c-pb-block-preview` | Yes | Every block container when previewed in Page Builder | +| `c-pb-block-preview` | Yes | Every block container in the Page Builder preview | | `c-pb-block-preview--is-dragging-out` | Yes | When a block is being dragged | | `c-pb-block-preview--is-removing` | Yes | When a block is being removed (see [Block removal (`blocks.remove`)](#block-removal-blocksremove)) | | `ibexa-mark-invisible` | Yes | When a scheduled block is marked as invisible | @@ -552,7 +551,7 @@ The always present `data-ibexa-block-id` attribute (`blockElement.dataset.ibexaB | `c-pb-block-preview__inner` | Yes | The inner container of a block | | `c-pb-block-preview__inner--invalid` | Yes | The inner container of a block with invalid attribute value | | `droppable-placeholder` | Yes | The placeholder element shown when a block is being dragged over a zone to indicate the drop position | -| `c-pb-block-preview--highlighted` | Yes | When a block is highlighted as when newly dropped | +| `c-pb-block-preview--highlighted` | Yes | When a block is highlighted, for example, when newly dropped | ## Implementation helpers @@ -570,11 +569,11 @@ TODO: To provide the .xsl files is enough to implement own converter. ### Static example -The following example is just a demo in vanilla JS provided as-is to illustrate the Page Builder protocol usage. -It can be used to observe the messages exchanged between the Page Builder and a front-end preview in the browser JS console. -It doesn't support all the block types or views. +The following vanilla JavaScript demo is provided as-is to illustrate how to use the Page Builder protocol. +You can use it to observe the messages exchanged between the Page Builder and a frontend preview in the browser's JavaScript console. +It does not support all block types or views. -- `page.html` is a static HTML page with some JS to handle the Page Builder protocol messages and basic CSS to show how conventional classes are for. +- `page.html` is a static HTML page with JavaScript that handles Page Builder protocol messages and demonstrates the intended uses of the conventional CSS classes. It works both as a standalone page and as a Page Builder preview. - `RichTextController.php` contains a controller that converts RichText to HTML. @@ -590,22 +589,22 @@ This example needs some setup on a development installation: ??? note "`page.html`" - ``` php hl_lines="175 527 778" + ``` html hl_lines="175 527 778" [[= include_code('code_samples/page/headless/page.html', indent_level=1) =]] ``` Edit `page.html`: -- Change the `apiBaseUrl` constant to declare the origin on which the REST API and the conversion controller are called. -- Change the `pbOrigin` constant to declare the origin of the Page Builder. -- Change the `pageContentTypeIds` to list content type IDs that have a Landing Page field. You can set this to `false` to skip the content type test. +- Change the `apiBaseUrl` constant to set the origin to which requests are sent for the REST API and conversion controller. +- Change the `pbOrigin` constant to set the Page Builder's origin. +- Change `pageContentTypeIds` to list the content type IDs that have a Landing Page field. You can set it to `false` to skip the content type check. `page.html` supports two layouts: - "Default layout for Landing Page" (`default`) - Custom "Two columns layout" (`2-columns`) -It supports the following block types and views: +The demo supports the following block types and views: - Text (`richtext`) block type with `default` view - Code (`tag`) block type with `default` and `source_code` views From b4293bfa58abdeaa5f720af854792e07a241494e Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Thu, 8 Oct 2026 11:12:53 +0200 Subject: [PATCH 26/31] headless_page_builder.md: Rewording --- docs/content_management/pages/headless_page_builder.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index c1f5137a698..954047d2e3b 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -260,8 +260,8 @@ Its data contains the field's new value, with the following structure: ### Re-dispatching events -The `PB:DISPATCH_EVENT` message is sent from the Page Builder to the front-end resource for being re-dispatched there as a custom event. -Its data contains the name of the event to dispatch (`eventName`) and the data to pass to the event detail (`eventData`). +The Page Builder sends the `PB:DISPATCH_EVENT` message to the frontend resource to be re-dispatched there as a custom event. +Its data contains the name of the event to dispatch (`eventName`) and the data to pass in the event's `detail` property (`eventData`). ```js window.addEventListener('message', (messageEvent) => { From 2b2d03d144b854fa7ac8309a6c37e31091aa7a2b Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Thu, 8 Oct 2026 13:25:36 +0200 Subject: [PATCH 27/31] eventData -> eventDetail; rm preview.params --- code_samples/page/headless/page.html | 15 +++++++-------- .../pages/headless_page_builder.md | 4 ++-- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/code_samples/page/headless/page.html b/code_samples/page/headless/page.html index a69187f2585..85ae02430dd 100644 --- a/code_samples/page/headless/page.html +++ b/code_samples/page/headless/page.html @@ -526,13 +526,12 @@ if (window.parent !== window) { // Inside the Page Builder iframe const pbOrigin = 'https://admin.example.com'; const capabilities = [ - 'blocks.dnd', // 100% - 'blocks.geometry', // 100% - 'blocks.remove', // 100% - 'blocks.reveal', // 100% - 'blocks.select', // 100% - 'pointer.tracking', // 100% - 'preview.params', // 0% + 'blocks.dnd', + 'blocks.geometry', + 'blocks.remove', + 'blocks.reveal', + 'blocks.select', + 'pointer.tracking', ]; const initInterval = 1500; // ms const initRetries = -1; // -1 = infinite, 0 = no retry, 1 = 1 retry, etc. @@ -682,7 +681,7 @@ positionsUpdate(); break; case 'PB:DISPATCH_EVENT': - window.dispatchEvent(new CustomEvent(messageEvent.data.data.eventName, {detail: messageEvent.data.data.eventData})); + window.dispatchEvent(new CustomEvent(messageEvent.data.data.eventName, {detail: messageEvent.data.data.eventDetail})); break; case 'PB:BLOCK_REMOVE': const blockId = messageEvent.data.data.blockId; diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index 954047d2e3b..2a185a9fcb0 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -261,13 +261,13 @@ Its data contains the field's new value, with the following structure: ### Re-dispatching events The Page Builder sends the `PB:DISPATCH_EVENT` message to the frontend resource to be re-dispatched there as a custom event. -Its data contains the name of the event to dispatch (`eventName`) and the data to pass in the event's `detail` property (`eventData`). +Its data contains the name of the event to dispatch (`eventName`) and the data to pass in the event's `detail` property (`eventDetail`). ```js window.addEventListener('message', (messageEvent) => { switch (messageEvent.data.type) { case 'PB:DISPATCH_EVENT': - window.dispatchEvent(new CustomEvent(messageEvent.data.data.eventName, { detail: messageEvent.data.data.eventData })); + window.dispatchEvent(new CustomEvent(messageEvent.data.data.eventName, { detail: messageEvent.data.data.eventDetail })); break; } }); From f3130bfcf5e362a79b1f55dca79fcb52a311a928 Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Thu, 8 Oct 2026 13:30:09 +0200 Subject: [PATCH 28/31] ibexa-post-update-blocks-preview customEvent.detail without s MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michał Grabowski --- docs/content_management/pages/headless_page_builder.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index 2a185a9fcb0..4df09b080b9 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -283,8 +283,8 @@ window.addEventListener('message', (messageEvent) => { ```js window.addEventListener('ibexa-post-update-blocks-preview', (customEvent) => { - setLayout(customEvent.details.fieldValue.layout); - renderZones(customEvent.details.fieldValue.zones); + setLayout(customEvent.detail.fieldValue.layout); + renderZones(customEvent.detail.fieldValue.zones); }); ``` From 1941507442884a21a2eac6dc68a2681d2e16ce29 Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Thu, 8 Oct 2026 13:31:20 +0200 Subject: [PATCH 29/31] PB:SCROLL_BY only top --- docs/content_management/pages/headless_page_builder.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index 4df09b080b9..60bfdafbe4e 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -416,7 +416,7 @@ const dropResponseMessage = { After the frontend sends `APP:DROP_RESPONSE`, the next `PB:UPDATE_FIELD_DATA` message from the Page Builder contains the dropped block's ID in its `highlightedBlockIds` array (`messageEvent.data.data.highlightedBlockIds`). The Page Builder sends the `PB:SCROLL_BY` message when a block is dragged near an edge of the preview, indicating that the preview needs to be scrolled. -Its data contains the amount to scroll vertically (`top`) or horizontally (`left`). +Its data contains the amount to scroll vertically (`top`). ```js window.addEventListener('message', (messageEvent) => { From 41fe902d6b8daaa22545b68ca78c20a0ccba6d66 Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Thu, 8 Oct 2026 13:33:41 +0200 Subject: [PATCH 30/31] pbOrigin to send APP:BLOCK_REMOVE_RESPONSE (from @GrabowskiM) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michał Grabowski --- docs/content_management/pages/headless_page_builder.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index 60bfdafbe4e..3d16d7d9cda 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -470,7 +470,7 @@ window.addEventListener('message', (messageEvent) => { data: { blockId: blockId, }, - }); + }, pbOrigin); }); blockElementToRemove.classList.add('c-pb-block-preview--is-removing'); } else { From 5b0309a2f60c0ab2c09dc1f6855cc91641735edf Mon Sep 17 00:00:00 2001 From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com> Date: Thu, 8 Oct 2026 13:38:58 +0200 Subject: [PATCH 31/31] PB:UPDATE_FIELD_DATA now always send all properties --- docs/content_management/pages/headless_page_builder.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/content_management/pages/headless_page_builder.md b/docs/content_management/pages/headless_page_builder.md index 3d16d7d9cda..8b2bbc87aa0 100644 --- a/docs/content_management/pages/headless_page_builder.md +++ b/docs/content_management/pages/headless_page_builder.md @@ -237,11 +237,10 @@ The `PB:UPDATE_FIELD_DATA` message is sent from the Page Builder to the frontend Its data contains the field's new value, with the following structure: -- Always included: the current value of the Landing page field being edited (`fieldValue`), including the layout, zones, and blocks. -
For example, only `fieldValue` is sent when you use the [timeline]([[= user_doc =]]/content_management/schedule_publishing/#timeline)![Timeline toggler icon](page_builder_toolbartimelinetoggler.png){style="display:inline;width:27px;vertical-align:middle;"}. -- Optionally, a list of the existing block types, their attributes, and their configuration (`blocksConfig`) -- Optionally, a block-ID-to-name mapping (`blocksIdMap`) -- Optionally, a list of IDs from the new blocks that have been added (`highlightedBlockIds`) +- the current value of the Landing page field being edited (`fieldValue`), including the layout, zones, and blocks. +- the list of the existing block types, their attributes, and their configuration (`blocksConfig`) +- the block-ID-to-name mapping (`blocksIdMap`) +- the list of IDs from the new blocks that have been added (`highlightedBlockIds`) ```json {