Org Skills

aem-universal-editor

Builds and instruments applications for the Universal Editor — the in-context authoring surface for AEM Sites pages, Edge Delivery Services sites and headless front ends.

Download .zip Raw Source
When agents use itCovers data-aue-* instrumentation, the AEM connection and CORS handshake, component and block model JSON, extensions, and the preview-to-publish flow. Use this whenever the user adds data-aue-resource, data-aue-prop, data-aue-type, data-aue-filter, data-aue-label or data-aue-model attributes, writes the urn:adobe:aue:system:aemconnection meta tag or loads universal-editor-service.adobe.io/cors.js, builds an Edge Delivery project from aem-boilerplate-xwalk with paths.json and per-block model, definition and filter JSON, asks why a component is not editable or not selectable in the editor, migrates off the deprecated SPA Editor, or makes a Next.js or React app editable against AEM. For the content API itself use `aem-headless`; for block behaviour use `aem-edge-delivery-services`.

Install

Copilot (VS Code, Visual Studio, Copilot CLI and github.com) reads skills from the repository — commit them so the whole team gets them.

npx skills add AGCO-Global/org-skills --skill aem-universal-editor -a github-copilot
# or with the org installer (adds .github/skills/aem-universal-editor):
npx -y github:AGCO-Global/org-skills add skill aem-universal-editor

Uses the open skills CLI. Works with Claude Code, Codex, Cursor, Copilot, Gemini CLI, OpenCode, Windsurf and 60+ others — it asks which agent to install into.

npx skills add AGCO-Global/org-skills --skill aem-universal-editor
# user-level instead of project-level:
npx skills add AGCO-Global/org-skills --skill aem-universal-editor -g

Installs the aem-development-skills plugin, which bundles all AEM / Development skills and keeps them updated.

/plugin marketplace add AGCO-Global/org-skills
/plugin install aem-development-skills@org-skills
# or just this skill, in this repository:
npx skills add AGCO-Global/org-skills --skill aem-universal-editor -a claude-code

Use Download .zip above, then upload it under Customize → Skills → Upload skill. Team and Enterprise admins can sync this repo as a plugin marketplace instead.

Installs into .agents/skills/, which Codex reads.

npx skills add AGCO-Global/org-skills --skill aem-universal-editor -a codex

Installs into Cursor's skills folder.

npx skills add AGCO-Global/org-skills --skill aem-universal-editor -a cursor

Installs into Gemini CLI's skills folder.

npx skills add AGCO-Global/org-skills --skill aem-universal-editor -a gemini-cli

Any tool with rules, instructions or custom prompts: use Copy SKILL.md above and paste it in. It is plain Markdown.

Commands use your normal git sign-in to GitHub, so they work while the repository is private. Node.js 20+ required.

Try it — example prompts

Prompts this skill is tested against, and what a good answer includes.

  • We author in AEM with Universal Editor; how do I define the block model?

    adobe-rnd/aem-boilerplate-xwalk template per-block JSON with definitions, models and filters paths.json maps repository paths to site routes fstab.yaml points at the AEM author environment field name becomes the property the block code reads

  • I added data-aue-resource and data-aue-prop to my React app but nothing is editable in the Universal Editor.

    checks the universal-editor-service.adobe.io/cors.js script is loaded checks the urn:adobe:aue:system:aemconnection meta tag connection must point at author, not publish author environment must allow the app's origin (CORS) verifies the resource URN resolves in that environment

  • Make this custom HTL teaser component editable in the Universal Editor.

    data-aue-resource on the component element and data-aue-prop per field data-aue-type of text, richtext or media per field data-aue-label for the name authors see Core Components 2.24+ already emit the attributes, so only custom components need them

  • We're on the SPA Editor with React. What should we do for a new site section?

    SPA Editor is deprecated (AEMaaCS 2025.01, 6.5.23), P1/P2 and security fixes only Universal Editor is the named successor for new work instrument the existing React app with data-aue-* rather than extending SPA Editor

  • Authors need to add and reorder cards inside our carousel block.

    data-aue-type="container" on the element holding the children data-aue-filter naming the allowed child components a filter entry in the block JSON matching the attribute each card is a component with its own resource

Skill contents

AEM Universal Editor

Targets: AEM as a Cloud Service 2026.x · Universal Editor (all AEM-backed front ends) · Verified: 2026-09 against https://experienceleague.adobe.com/en/docs/experience-manager-cloud-service/content/implementing/developing/universal-editor/getting-started

The Universal Editor edits your rendered application, not an AEM-specific rendering of it. You describe what each piece of markup maps to in the content repository, and the editor builds the authoring UI from that. So the work is almost entirely instrumentation and content modelling: get the resource URNs and property names right and everything else follows; get them wrong and the page looks fine to a visitor and is uneditable to an author.

SPA Editor is deprecated (AEMaaCS 2025.01, 6.5.23; P1/P2 and security fixes only). Universal Editor is the successor for every new project.

1. Decide first

Question Default Change when
Which front end Edge Delivery Services with the adobe-rnd/aem-boilerplate-xwalk template AEM Sites HTL when you need the full component/policy model; a custom React/Next app when the front end is owned elsewhere
Instrumenting HTL components Nothing to do — Core Components ≥ 2.24 already emit data-aue-* Hand-write attributes only for custom components that do not extend a Core Component
Where the content lives The AEM repository the aemconnection meta tag points at Headless apps still edit Content Fragments — same attributes, different resource URNs
Model definition for EDS Per-block _<block>.json (model, definition, filter) in the block folder A single central model file only for a tiny site
Editable unit data-aue-type="component" on the block, prop on each field container when authors add and reorder children
Auth for the editor The author's own IMS login through the editor Service credentials never belong in the front end
Publishing Author edits → preview → publish through the editor's own flow A separate CI publish only for code, never for content

2. Instrument the markup

Four attributes carry the whole contract:

<div data-aue-resource="urn:aemconnection:/content/site/en/home/jcr:content/hero"
     data-aue-type="component"
     data-aue-label="Hero">
  <h1 data-aue-prop="title" data-aue-type="text">Summer collection</h1>
  <div data-aue-prop="body" data-aue-type="richtext">…</div>
  <img data-aue-prop="image" data-aue-type="media" src="/content/dam/site/hero.jpg" alt="">
</div>
  • data-aue-resource — the resource the node maps to, as a URN. Everything below it is addressed relative to it, so one wrong path silently disables a whole subtree.
  • data-aue-prop — the property name on that resource. It must match the stored property exactly, including case.
  • data-aue-type — how to edit it: text, richtext, media, container, component, reference.
  • data-aue-label, data-aue-filter, data-aue-model — the name authors see, which components may be added inside a container, and which model backs the item.

Full attribute and type semantics, plus the nesting rules for containers: references/instrumentation.md.

3. Connect the app to AEM

Two tags in the document head, and nothing else:

<meta name="urn:adobe:aue:system:aemconnection" content="aem:https://author-p1234-e5678.adobeaemcloud.com">
<script src="https://universal-editor-service.adobe.io/cors.js" async></script>
  • The connection meta tag names the author environment — the editor writes there. Point it at publish and nothing saves.
  • cors.js performs the cross-origin handshake between your app and the editor service. Without it the page renders normally and the editor sees no editable content at all — the single most common "why is nothing editable" cause.
  • The AEM author environment must allow your app's origin. A CORS failure here looks identical to missing instrumentation, so check the browser console before re-reading your attributes.
  • Ship instrumentation only where it is wanted: data-aue-* in a public production build exposes repository paths.

4. Content models

AEM Sites (HTL). Core Components ≥ 2.24 emit the attributes themselves; a custom component needs them added to its HTL, and its dialog still defines the fields.

Edge Delivery Services (xwalk). Start from adobe-rnd/aem-boilerplate-xwalk. Each block carries its own JSON beside its code:

  • model — the fields an author edits, and their types.
  • definition — how the block appears in the editor's component list.
  • filter — which components may be placed inside it.

fstab.yaml points at the AEM author environment rather than a document source, and paths.json maps repository paths to site routes. Get paths.json wrong and pages render but resource URNs do not resolve.

Worked block JSON for all three files: references/xwalk-block-models.md.

5. Extensions

The editor's UI is extensible through App Builder extensions — custom rail panels, toolbar actions and field types. Reach for one only when authors need something the standard editor cannot express; an extension is an application to own and upgrade, not configuration.

Deliverable format

## Target — which front end, which AEM environment, which content model
## Instrumentation — the markup with data-aue-* attributes, per component or block
## Connection — meta tag, cors.js, CORS policy on author, and where each is set
## Models — block/component model, definition and filter JSON (or the dialog for HTL)
## Paths — paths.json mapping (EDS) or the resource URN scheme (Sites/headless)
## Verification — what to click in the editor to prove each field is editable
## Open questions

Checklist

  • Every editable region has a data-aue-resource that resolves in the target environment.
  • Every data-aue-prop matches the stored property name exactly, including case.
  • Every prop has a data-aue-type, and containers declare a data-aue-filter.
  • The aemconnection meta tag points at author, not publish.
  • cors.js is loaded, and author allows the app's origin.
  • EDS: each block has model, definition and filter JSON, and paths.json maps its routes.
  • Authors can add, reorder and delete children wherever the design allows it.
  • Instrumentation is absent, or harmless, in the public production build.
  • The change was verified in the editor, not only in the rendered page.

Anti-patterns

Anti-pattern Why it hurts Fix
Pointing aemconnection at the publish tier Edits appear to work and never persist Point at the author environment
Omitting cors.js Nothing is editable, with no error on the page Load it in the head, async
Hand-instrumenting Core Components Duplicate and conflicting attributes Upgrade to Core Components ≥ 2.24 and delete the hand-written ones
data-aue-prop guessed from the label Silently unsaveable field Read the property name from the model or the node
A container with no data-aue-filter Authors can insert anything, including components that break the layout Declare the allowed components
Starting a new project on SPA Editor Deprecated since AEMaaCS 2025.01; fixes only Use the Universal Editor from the start
Building an extension for a small gap An app to maintain forever Model it in the block JSON first

Go deeper

  • references/instrumentation.md — every attribute and type, nesting and container rules, and the failure each mistake produces.
  • references/xwalk-block-models.md — model, definition and filter JSON for an EDS block, with paths.json and fstab.yaml.
  • Sibling skills: aem-edge-delivery-services for block code and performance; aem-headless for the content API; aem-component-development for HTL components and dialogs.

References

Deeper material the agent loads only when needed.