Org Skills

Edge Delivery blocks authored in the Universal Editor (xwalk)

Supporting material for aem-universal-editor. Agents load it on demand; it ships inside the skill folder.

RawSource

Verified 2026-09 against https://experienceleague.adobe.com/en/docs/experience-manager-learn/sites/edge-delivery-services/developing/universal-editor/1-new-code-project.

A UE-authored Edge Delivery project starts from the adobe-rnd/aem-boilerplate-xwalk template rather than the document-authored boilerplate. Content lives in AEM, not in a spreadsheet or document source.

Project wiring

fstab.yaml points at the AEM author environment:

mountpoints:
  /: https://author-p1234-e5678.adobeaemcloud.com/bin/franklin.delivery/myorg/myrepo/main

paths.json maps repository paths to site routes:

{
  "mappings": [
    "/content/myproject/:/"
  ],
  "includes": [
    "/content/myproject/"
  ]
}

If a page renders but the editor cannot resolve its resource, paths.json is the first thing to check — the mapping is what turns a site route back into a repository path.

Per-block JSON

Each block owns three definitions, conventionally in blocks/<block>/_<block>.json. A teaser block:

{
  "definitions": [
    {
      "title": "Teaser",
      "id": "teaser",
      "plugins": {
        "xwalk": {
          "page": {
            "resourceType": "core/franklin/components/block/v1/block",
            "template": {
              "name": "Teaser",
              "model": "teaser"
            }
          }
        }
      }
    }
  ],
  "models": [
    {
      "id": "teaser",
      "fields": [
        { "component": "text",      "name": "title",    "label": "Title",    "valueType": "string" },
        { "component": "richtext",  "name": "body",     "label": "Body",     "valueType": "string" },
        { "component": "reference", "name": "image",    "label": "Image",    "valueType": "string" },
        { "component": "text",      "name": "ctaLabel", "label": "CTA label","valueType": "string" },
        { "component": "aem-content","name": "ctaLink", "label": "CTA link", "valueType": "string" }
      ]
    }
  ],
  "filters": []
}
  • definitions — what appears in the editor's component list, and which model a new instance uses.
  • models — the fields an author edits. name becomes the property name, and therefore the value your block's JavaScript reads; renaming it orphans existing content.
  • filters — for a block that contains other blocks, the ids that may be placed inside it. A container block with an empty filter list accepts nothing.

Container blocks

A block whose children authors manage needs a filter entry naming the allowed child ids, and the rendered markup needs data-aue-type="container" on the element holding the children. The two must agree: the filter controls what the editor offers, the attribute controls where it is inserted.

Keeping the model and the code in step

The block's decorate() reads the DOM the model produced. When you add a field, add it to the model and to the markup contract at the same time, and check an existing authored instance still decorates — a field inserted in the middle shifts the row order that older blocks rely on.