Enable visual editing
The framework-agnostic documentation is under development. If you have suggestions for improving the content, let us know by sharing your Feedback at the bottom of this page.
This walkthrough explains how to enable WYSIWYG editing for content authors working in the SitecoreAI Page builder, which is a key development task with Sitecore. By the end of the walkthrough, the Page builder will display your front-end app in an iframe and enable content authors to edit page contents directly in the canvas:
The walkthrough provides code examples for Astro (v7) and Go (v1) front-end applications, and it describes how to:
- Configure your Sitecore environment variables
- Retrieve editing layout data using GraphQL
- Add metadata wrappers to the HTML
- Create
/api/editing/config - Create
/api/editing/render - Register the new endpoints
- Connect the Page builder to
localhost - Test visual editing
- Complete the Render SitecoreAI content in your app walkthrough. This walkthrough builds directly on the app you built there.
- Review how visual editing works.
- Open your front-end project in your code editor, and your site in the Page builder.
Configure your Sitecore environment variables
In addition to the identifiers you previously set up for content rendering, more identifiers are needed for your front-end app to securely communicate with the Page builder. In Node-based applications, these are typically stored in a .env file, but you should use the appropriate method for the language and framework you are building with.
Secrets such as API keys, editing secrets, and Context IDs must never be hard-coded or exposed to the browser. It's best practice to store them in environment variables or a secrets manager instead.
| Name | Description | Example |
|---|---|---|
SITECORE_EDITING_SECRET | The Sitecore editing secret. Required for the Page builder to retrieve data from your front-end app. Find the value in SitecoreAI Deploy > Projects > your project > Authoring environments > your environment > Developer settings > Environment variables > the value for SITECORE_EDITING_SECRET in the code block.If you cannot see SITECORE_EDITING_SECRET, ensure Context > Preview is selected. | 6lrpCn... |
Also make sure you use the Preview Context ID, not the Live Context ID. Visual editing always accesses draft (unpublished) content, accessed using the Preview Context ID.
Retrieve editing layout data using GraphQL
The /api/editing/render endpoint uses the editing GraphQL query, which is different from the one used for normal page rendering.
Select your framework and follow the steps to make this query in your front-end app:
Both editing endpoints share the same CORS logic. Before creating the endpoints, consider extracting ALLOWED_ORIGINS and getCorsHeaders into a shared module (for example, src/services/editingCors.js) and importing it in both endpoint files. The code examples below include the full implementation inline for clarity.
-
In
src/services/sitecoreClient.js, add the following function after the existingfetchLayoutDatafunction:
-
To create the query, create
editing.goand paste the following code:
Note that these scripts retrieve the dictionary but don't consume it because the components don't contain translatable UI strings.
Add metadata wrappers to the HTML
Next, you add the <code> metadata blocks that the Page builder needs to identify placeholders, components, and individual fields in the HTML your app renders.
To add metadata wrappers:
-
Create
src/services/editingRenderer.jsand paste the following code: -
In
src/components/componentMap.js, addContainerFullBleedalongside the other passthrough components you registered when following the content rendering walkthrough:
-
Create
editing_rendering.goand paste the following code: -
Update the component renderers in
components.goto callmetaFieldon each field value. BecausemetaFieldreturns the HTML unchanged whenmetadatais absent, the same renderers work in both normal and editing mode:Also add
ContainerFullBleedto thecomponentRegistryinit()block incomponents.go, using the same passthrough renderer asPartialDesignDynamicPlaceholder:
Create /api/editing/config
/api/editing/configThe /api/editing/config endpoint tells the Page builder which editing mode your app uses and which component names it supports. The Page builder calls this endpoint every time it connects to an editing host. For example, when a content author opens the editor, or when you change between local and hosted editing hosts. For the response payload this endpoint must return, see the config response.
To create the /api/editing/config endpoint:
-
Create
src/pages/api/editing/config.jsand paste the following code:
-
Create
api_editing_config.goand paste the following code:
Create /api/editing/render
/api/editing/renderThe /api/editing/render endpoint is the core of the editing integration. When a content author views a page in the editor, the Page builder loads the editing canvas by setting the iframe src to this endpoint. The browser then makes a GET request to your app with the editing parameters in the URL. Your app retrieves the editing layout data from Sitecore and returns a complete HTML page to the Page builder, with metadata code blocks embedded. The Page builder will load this HTML page inside an iframe.
If your app sets X-Frame-Options: SAMEORIGIN or a Content-Security-Policy header with frame-ancestors 'self', the iframe will be blocked. Either remove those headers for the editing render endpoint responses, or add https://pages.sitecorecloud.io as an allowed framing origin.
To create the /api/editing/render endpoint:
-
Create
src/pages/api/editing/render.jsand paste the following code:
The editing canvas must render with the same styles and scripts as the published site. In Go, the editing renderer achieves this by reusing the existing pageTmpl page template from layout.go rather than defining a separate HTML document structure. Any CSS and JavaScript you add to pageTmpl for normal rendering automatically appears in the editing canvas too.
-
Update
layout.goto extendpageVarsandpageTmplwith editing support:The two additions to
layout.goare:EditingHeadScripts template.HTMLinpageVars- empty for normal rendering, populated by the editing renderer.{{.EditingHeadScripts}}in<head>and the conditionaljss-hrz-editingmarker at the end of<body>. Both are no-ops when the field is empty, so normal page rendering is unaffected.
-
Create
api_editing_render.goand paste the following code:
Register the new endpoints
After creating the endpoints, update your HTTP server and register the endpoints.
To register the new endpoints:
Astro uses file-based routing, so creating the files in the previous two procedures automatically registers the endpoints at /api/editing/config and /api/editing/render, with no additional registration required.
-
Update
main.goto register the two new editing endpoints before the catch-all/handler:
Connect the Page builder to localhost
localhostYour app is now ready to be loaded into the Page builder iframe. You can connect the Page builder directly to your running local server without deploying. This lets you test components without affecting other SitecoreAI users.
To connect the Page builder to localhost:
-
In
astro.config.mjs, addsecurity.allowedDomainsandvite.server.cors:- Without
security.allowedDomains, Astro returns403 Forbiddenfor every request frompages.sitecorecloud.iobefore your endpoint code runs, regardless of the CORS headers your endpoints set. - Without
vite.server.cors: false, Vite's built-in CORS middleware intercepts everyOPTIONSpreflight frompages.sitecorecloud.ioand responds withAccess-Control-Allow-Origin: *, but never adds theAccess-Control-Allow-Private-Network: trueheader. When an HTTPS page accesses a private network address (localhost), browsers require this header in the preflight response before sending the real request. The browser blocks the request and your AstroOPTIONShandler never runs.
- Without
-
Start your development server:
-
Open your site in the Page builder.
-
In the Page builder, on the ribbon directly above the canvas, to the right of the Version selector, click Default editing host, select Local host, and then enter your app's localhost address, such as
http://localhost:4321. -
Click Save.
-
Verify that the Page builder loads your app in the canvas.
-
Test visual editing.
When the Page builder at pages.sitecorecloud.io (an HTTPS origin) connects to your localhost server (a private network address), browsers send a Private Network Access preflight OPTIONS request before the real GET /api/editing/config. The /api/editing/config endpoint handles this preflight and responds with the Access-Control-Allow-Private-Network: true header alongside the standard CORS headers. The /api/editing/render endpoint is loaded as an iframe navigation, not a subresource fetch, so browsers do not send a Private Network Access preflight for it. If you see a blank canvas or a CORS error in the browser console, check the Network tab for a failed OPTIONS request to /api/editing/config and verify that your server is running and returning those headers.
-
Start your development server:
-
Open your site in the Page builder.
-
In the Page builder, on the ribbon directly above the canvas, to the right of the Version selector, click Default editing host, select Local host, and then enter your app's localhost address, such as
http://localhost:3000. -
Click Save.
-
Verify that the Page builder loads your app in the canvas.
-
Test visual editing.
Test visual editing
After the Page builder displays your app in the canvas, test visual editing to make sure common editing interactions work.
To test visual editing:
- Start or restart your development server.
- Open your site in the Page builder and connect it to localhost.
- Verify that the Page builder loads your app in the canvas.
- In your web browser's developer console, on the Network tab, find a request to
/api/editing/config, and read the request and response details. A successful/api/editing/configresponse returns{"editMode":"metadata","components":[...]}. - Make a change to a field. For example, edit a text, and then verify that the change appears in localhost after you refresh the page.
- Drag a component to a different position in the canvas and verify that the change appears in localhost after you refresh the page.
Next steps
You've now set up your front-end app in localhost to appear and be editable in the Page builder.
Next, you can:
- Test with multiple page types to confirm all your component implementations are correctly mapped and render with metadata in the canvas.
- Deploy your app and connect the Page builder to it.