Publishing AEM Content Fragments to Edge Delivery Services
AEM content fragments are used to create, manage, and deliver content across multiple channels. Until recently, publishing content fragments to Edge Delivery Services only embedded a reference to the content fragment—not the actual content—in the semantic HTML. This can limit a LLM agents’ ability to ingest and understand the content or create a meaningful search index for a page.
With the approach described next, you can publish AEM Content Fragments to Edge Delivery Services as self-contained semantic HTML.
Why Does This Matter?
1. LLM/SEO Optimization
LLM and SEO optimization improve because content fragments are now published as self-contained semantic HTML. Previously, only links to fragments were included, so automated agents like search engines and language models could not access the full content. Now, the complete content is directly available without requiring JavaScript.
2. Omnichannel Delivery
Omnichannel delivery like banners, press releases, blog posts etc. can be managed and published as full web pages instead of only as headless content. Edge Delivery Services acts as the “head” for the headless CMS, providing HTML output for any channel.
3. Simplified Workflow
In the current approach, GraphQL endpoints and queries must be defined and published together with the fragments. For each content fragment model, a separate block is created and then added to an AEM page. Finally, the page itself is published, containing only a reference to the content fragment rather than the fragment’s full content.
The new approach streamlines this significantly. Instead of working with GraphQL endpoints, you define path mapping and overlay directly in the site configuration. The json2html service is then configured, and a Mustache template is applied to transform the JSON output of the fragments into HTML.
With this setup, the content fragments can be published directly as HTML, eliminating the need for additional blocks, queries or pages.
How to Set It Up
As a prerequisite you need:
- An AEM as a Cloud Service (AEMaaCS) environment.
- A site using the aem-boilerplate-xwalk project template or similar.
- Repoless setup enabled in Edge Delivery Services.
- Enable Content Fragments for your site.
For our example we are going to use a content fragment model for press releases with fields like title
, author
, text
and image
.
Next we create Content Fragments in a dedicated assets folder (e.g., below press
) using the press release model.
Step 1: Configure Path Mapping and Overlay in Configuration Service
In the Configuration Service, define the published path for your content fragments. In our example we publish them directly below /press
.
"public": {
"paths": {
"mappings": [
"/content/xwalk-omnichannel/:/",
"/content/dam/xwalk-omnichannel/press/:/press/"
]
}
}
Add an overlay to the content source section in your org’s config, pointing to the json2html service.
"content": {
"source": {
"url": "https://author-pXXXX-eXXXX.adobeaemcloud.com/bin/franklin.delivery/adobe-rnd/xwalk-omnichannel/main",
"type": "markup",
"suffix": ".html"
},
"overlay": {
"url": "https://json2html.adobeaem.workers.dev/adobe-rnd/xwalk-omnichannel/main",
"type": "markup"
},
}
The URL format for the json2html service is:
https://json2html.adobeaem.workers.dev/ORG/SITE/BRANCH
How the overlay works:
- When a content fragment gets published, the admin API checks the overlay source first.
- The json2html service fetches the content fragment JSON.
- It transforms the JSON to HTML using a Mustache template.
- The HTML is ingested by the Admin API.
Step 2: Configure the json2html Service
The following is the curl command to set up the service for our example use case:
curl --request POST \
--url https://json2html.adobeaem.workers.dev/config/adobe-rnd/xwalk-omnichannel/main \
--header 'Authorization: token <admin-api-token>' \
--header 'Content-Type: application/json' \
--data '[
{
"path": "/press/",
"endpoint": "https://author-pXXXX-eXXXX.adobeaemcloud.com/api/assets/xwalk-omnichannel/press/{{id}}.json",
"regex": "/[^/]+$/",
"template": "/cf-templates/press.html",
"relativeURLPrefix": "https://publish-pXXXX-eXXX.adobeaemcloud.com",
"headers": {
"Accept": "application/json"
},
"forwardHeaders":[
"Authorization"
]
}
]
See the documentation for the json2html Service for a detailed description of the different configuration options. In short:
path
: Defines the URL paths for which the service should process requests. In our example the root path in Edge Delivery Service where we publish the press releases ,/press/
.endpoint
: The URL of the JSON endpoint that returns the content fragment data from your AEM author instanceregex
: A regular expression to extract a specific part of the published URL (e.g., the Content Fragment ID). The extracted value is used as the{{id}}
parameter in theendpoint
.template
: The path to your Mustache.js template file, which transforms the JSON data into semantic HTML. Store the template in your Edge Delivery Services github project.relativeURLPrefix
: Converts relative URLs (for images, videos, or other assets) into absolute URLs, ensuring the admin API can ingest and render all linked assets. Set this to the base URL of your AEM publish instance.headers
: HTTP headers to include in the request to the JSON endpoint.forwardHeaders
: Specifies which HTTP headers should be forwarded from the admin API to the JSON endpoint, required for authenticated requests.
Step 3: Create a Mustache Template
Without a template, each property in your JSON is rendered as a <div>
. To create a more meaningful semantic HTML for our press release example we define a template that renders:
- the first image and the press release title as an hero block
- the author name as default content
- the news article and two images in a columns block
<!DOCTYPE html>
<html>
<head>
<title>{{properties.title}}</title>
</head>
<body>
<header></header>
<main>
<div>
<div class="hero">
<div>
<div>
<p>
<picture>
<img src="{{{properties.elements.image.value}}}">
</picture>
</p>
<h1>{{properties.elements.newsTitle.value}}</h1>
</div>
</div>
</div>
<p><strong>Author:</strong> {{properties.elements.author.value}}</p>
<div class="columns">
<div>
<div>
<p>
<picture>
<img src="{{{properties.elements.image2.value}}}">
</picture>
</p>
</div>
<div>
<p>{{{properties.elements.text.value}}}</p>
</div>
<div>
<p>
<picture>
<img src="{{{properties.elements.image3.value}}}">
</picture>
</p>
</div>
</div>
</div>
</div>
</main>
<footer></footer>
</body>
</html>
Key Points:
- Use Mustache.js syntax.
- Ensure all asset paths are absolute or use
relativeURLPrefix
to append the right domain to the relative urls in the content. - Follow Edge Delivery Services semantic HTML guidelines to create valid semantic HTML that can be ingested by the admin API.
Test Your Setup
- Create and publish a content fragment to Edge Delivery Service.
- Verify the output is a standalone HTML page with all content rendered.
For our example the output looks as follows:
Conclusion
By setting up an overlay using the json2html service, you can now publish AEM content fragments as self-contained semantic HTML to Edge Delivery Services. This simplifies omnichannel delivery and makes your content LLM-ready—all with minimal setup.
Previous