Integrating AEM Universal Editor with a Next.js App
The AEM Universal Editor lets authors edit content directly inside your existing Next.js experience while still treating AEM as a headless CMS
Universal Editor with a Server Side Rendered App
This guide walks through the core integration steps, assuming:
- AEM as a Cloud Service with Content Fragments and GraphQL
- A Next.js app that already fetches content from AEM
For background on the broader AEM headless CMS architecture — Content Fragment Models, GraphQL endpoint design, delivery API tradeoffs, and when headless is the right call — see AEM Headless CMS: Architecture, GraphQL, and Implementation. For Universal Editor use cases and official documentation, see Universal Editor Use Cases and Learning Paths.
Connect Next.js to AEM Headless (Content Fragments + GraphQL)
First make sure your Next.js app is already consuming AEM headless content:
- Model your content in AEM as Content Fragments and publish your GraphQL endpoint.
- From Next.js, call the GraphQL endpoint (SSR, ISR, or client‑side – any is fine).
async function fetchArticles() {
const res = await fetch(
'https://publish-pXXXX-eYYYY.adobeaemcloud.com/graphql/execute.json/my-endpoint',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: '{ articleList { items { _path title body } } }' }),
}
);
return res.json();
}
Bootstrap Universal Editor in your Next.js <head>
In your root layout (e.g., _document.tsx or app/layout.tsx), add the AEM connection meta tag and Universal Editor CORS script to the <head>.
Key points:
- Always point
aemconnectionat Author for editing (aem:https://author-…). - Use
https://universal-editor-service.adobe.io/cors.js(do not use older URLs).
Mark editable regions with data-aue-* attributes
The Universal Editor inspects your rendered HTML and uses data-aue-* attributes to know what is editable, where the content lives in AEM, and how to render the editing UI.
A simple example for text stored in a Content Fragment field:
export function ArticleTeaser({ fragmentPath, title }) {
return (
<h2
data-aue-resource={`urn:aemconnection:${fragmentPath}`}
data-aue-type="content-fragment"
data-aue-field="title"
>
{title}
</h2>
);
}
Wire preview vs live correctly (AEM + Next.js)
You'll usually have two frontends:
- Preview Next.js domain → calls AEM Preview GraphQL
- Live Next.js domain → calls AEM Publish GraphQL
Universal Editor itself always connects to Author; your Next.js app decides whether it reads Preview or Publish when running outside UE.
Open your Next.js app in Universal Editor
- Deploy your Next.js app to a URL UE can reach (dev/stage/preview).
- In AEM, open the Universal Editor (via Sites console or direct URL).
- Provide the public URL of your Next.js page as the "canvas" URL.
- The Universal Editor will load your page, inspect
data-aue-*attributes, and let authors edit fields inline or via the properties rail.
Where to go deeper
Once the main flow is working, typical next steps are adding definitions for richer components and models, handling authentication for protected environments, and adding a "preview URL" meta tag if you want UE's Open page button to use a specific frontend URL.
For more detailed examples, the React + Universal Editor tutorial is the best reference. React app editing using Universal Editor
Related architecture and labs
- AEM Headless CMS: Architecture, GraphQL, and Implementation — the full architecture picture: Content Fragment Models, persisted GraphQL queries, delivery API tradeoffs, and when headless is the right call.
- AJO Code-Based Experience on EDS — connecting AJO personalization to an Edge Delivery Services page via Web SDK. Shows how AEM headless content and AJO work together at the delivery layer.
- Editing AJO Emails with Universal Editor — a POC using Content Fragments and Universal Editor to enable in-context editing of AJO email content.