Developers · Mark content

Primitive reference

Built-in node types that map native HTML (or an explicit data-macro-type) to editable content. Prefer primitives for single-purpose fields; use custom components when several fields share one layout.

Try every primitive
The demo site ships a live matrix at primitives.html. Use it to verify inference, inline edit, and overlay panels before shipping markup.

How inference works

When the SDK finds a data-macro-key, it resolves a typeId in this order:

  1. Explicit data-macro-type (short form like richtext or full macro/richtext / @acme/hero).
  2. Registered custom element tag from a MacroNodeDefinition.
  3. Built-in tag inference (for example <img>macro/image).
  4. Fallback: macro/text for unmatched tags.
Richtext is never inferred from a bare div
A plain <div> or <section> becomes text, not richtext. Always set data-macro-type="richtext" (or macro/richtext) for HTML bodies.

Markup patterns

infer.html
<h1 data-macro-key="home.title">Welcome</h1>
<img data-macro-key="home.hero" alt="" />
<a data-macro-key="home.cta" href="/pricing">Pricing</a>
NameTypeRequiredDescription
data-macro-keystringrequiredStable content key for the website (no locale suffix).
data-macro-typestringoptionalBuiltin short name, macro/* id, or custom @scope/name typeId.

Type matrix

Payload shapes below are the fields editors see in the overlay / Dashboard. The SDK seeds and hydrates them via DOM bindings — you usually only mark the host element.

NameTypeDescription
macro/textTEXTh1–h6, p, span, strong, em, label, button, li, td, th, a without href, … → { text }
macro/richtextRICHTEXTOnly with data-macro-type="richtext" (or macro/richtext) → { html }
macro/imageIMAGEimg → { assetId, alt, caption }
macro/linkLINKa[href] → { text, href, target, rel }; Shift+click to navigate while editing
macro/videoVIDEOvideo → asset + poster + playback flags
macro/audioAUDIOaudio → asset + controls/loop
macro/embedEMBEDiframe / embed → { url, title }
macro/picturePICTUREpicture → asset, alt, sources JSON
macro/iconICONsvg → svg markup and/or assetId
macro/attr-textATTR_TEXTinput (text-like), textarea → value, placeholder, label, …
macro/selectSELECTselect → selected + options JSON
macro/checkboxCHECKBOXinput[type=checkbox] → checked, value, label
macro/radioRADIOinput[type=radio] → checked, value, label
macro/groupREPEATERHTML repeaters / items-slot runtime host

Text

macro/text covers headings, paragraphs, spans, buttons, list items, table cells, and anchors without href. Payload: { text }. Inline editing is on by default.

text.html
<h1 data-macro-key="home.title">Welcome</h1>
<p data-macro-key="home.lead">One sentence under the hero.</p>
<button type="button" data-macro-key="home.ctaLabel">Get started</button>

Richtext

Payload: { html }. Use for multi-paragraph or formatted copy. The overlay offers a rich editor; inline editing is available when the host is selected.

richtext.html
<div
  class="prose"
  data-macro-key="about.body"
  data-macro-type="richtext"
>
  <p>Long-form copy with <strong>formatting</strong>.</p>
</div>

Image

Inferred from <img>. Payload: assetId, alt, caption. Store the Macro asset UUID — never bake CDN URLs into content keys. The context bar exposes “Choose image”.

image.html
<img
  data-macro-key="home.heroImage"
  alt="Hero"
  width="1600"
  height="900"
/>

Link

Inferred from <a href>. Payload: text, href, target, rel. While the editor is open, a normal click selects the link; editors navigate with Shift+click.

link.html
<a data-macro-key="nav.pricing" href="/pricing">Pricing</a>

Media: video, audio, embed, picture, icon

macro/video

Tag <video>. Fields: assetId (video MIME), posterAssetId, controls, loop, muted.

html
<video
  data-macro-key="home.reel"
  controls
  playsinline
></video>
macro/audio

Tag <audio>. Fields: assetId, controls, loop.

macro/embed

Tags <iframe> / <embed>. Fields: url, title. Prefer trusted embed URLs; your site still owns CSP.

html
<iframe
  data-macro-key="home.map"
  data-macro-type="embed"
  title="Map"
  loading="lazy"
></iframe>
macro/picture

Tag <picture>. Fields: assetId, alt, sources (JSON for art-direction sources).

macro/icon

Tag <svg>. Fields: inline svg markup and/or assetId for an image asset. Prefer SVG when you need color inheritance via currentColor.

Form field primitives

Macro edits field values only. Keep action, method, name, and server handling in your HTML. Full walkthrough: Form primitives.

form.html
<form action="/api/contact" method="post">
  <label>
    <span data-macro-key="contact.emailLabel">Email</span>
    <input
      name="email"
      type="email"
      data-macro-key="contact.email"
      data-macro-type="attr-text"
    />
  </label>
  <button type="submit" data-macro-key="contact.submit">Send</button>
</form>

Groups / repeaters

macro/group powers HTML repeaters and component items slots. Prefer Groups & repeaters for page-level lists, and Slots: items when the list lives inside a custom component.

Keys, locales, and draft/live

  • data-macro-key is unique per website. Do not put locale codes inside the key — locale is a save/view dimension, not part of the key string.
  • Draft and live payloads share the same keys; publish promotes draft → live.
  • Sitewide keys (header/footer) use the same primitives — see Sitewide content.

Payload cheat sheet

payloads.json
{
  "macro/text": { "text": "Welcome" },
  "macro/richtext": { "html": "<p>Hello</p>" },
  "macro/image": { "assetId": "<uuid>", "alt": "Hero", "caption": "" },
  "macro/link": { "text": "Pricing", "href": "/pricing", "target": "", "rel": "" },
  "macro/attr-text": { "value": "", "placeholder": "[email protected]", "label": "Email" },
  "macro/select": { "selected": "de", "options": [{ "value": "de", "label": "Deutsch" }], "label": "Language" },
  "macro/checkbox": { "checked": false, "value": "1", "label": "Subscribe" }
}

Do

  • Rely on tag inference for text, images, and links when the HTML already expresses intent.
  • Mark richtext explicitly every time.
  • Keep one key = one content concern (one heading, one image, one CTA label).
  • Use Shift+click to follow links while editing.

Don’t

  • Don’t wrap a single H1 in a custom component — use macro/text.
  • Don’t put locale codes or environment names inside data-macro-key.
  • Don’t store permanent CDN URLs in content when an asset UUID exists.
  • Don’t expect Macro to own form action / submission endpoints.

Related