Developers · Mark content

Form primitives

Macro stores editable field values (text, selection, checked state). Your HTML still owns form action, method, names, validation, and server handling.

Boundary
Treat Macro as a content layer for labels and defaults — not as a form backend. Submission endpoints stay on your stack.

When to use form primitives

  • Marketing or contact forms where editors change copy, placeholders, or default options.
  • UI chrome that must stay editable (button labels next to inputs).
  • Not for auth secrets, payment fields, or anything that must not be CMS-controlled.

Built-in types

NameTypeDescription
macro/attr-textATTR_TEXTText-like inputs and textarea — value, placeholder, label, …
macro/selectSELECTSelect — selected value + options JSON
macro/checkboxCHECKBOXCheckbox — checked, value, label
macro/radioRADIOSingle radio — checked, value, label
macro/radio-groupRADIO_GROUPGrouped radios — selected + options (when used as a group node)

attr-text (inputs & textareas)

Covers text-like <input> types (including email, password, range, color) and <textarea>. Typical payload keys: value, placeholder, label, plus type-specific attrs the overlay exposes.

attr-text.html
<label>
  <span data-macro-key="contact.emailLabel">Email</span>
  <input
    name="email"
    type="email"
    required
    data-macro-key="contact.email"
    data-macro-type="attr-text"
  />
</label>

<textarea
  name="message"
  rows="5"
  data-macro-key="contact.message"
  data-macro-type="attr-text"
></textarea>

Select

Payload: selected, options (JSON array of { value, label }), label. Editors change the selected value and can maintain option lists from the sidebar.

select.html
<label>
  <span data-macro-key="contact.topicLabel">Topic</span>
  <select name="topic" data-macro-key="contact.topic" data-macro-type="select">
    <option value="sales">Sales</option>
    <option value="support">Support</option>
  </select>
</label>

Checkbox & radio

checkbox.html
<label>
  <input
    type="checkbox"
    name="newsletter"
    value="1"
    data-macro-key="contact.newsletter"
    data-macro-type="checkbox"
  />
  <span data-macro-key="contact.newsletterLabel">Send me updates</span>
</label>

Complete contact form example

contact.html
<form class="contact" action="/api/contact" method="post">
  <label>
    <span data-macro-key="contact.nameLabel">Name</span>
    <input name="name" data-macro-key="contact.name" data-macro-type="attr-text" />
  </label>
  <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>
  <label>
    <span data-macro-key="contact.messageLabel">Message</span>
    <textarea
      name="message"
      data-macro-key="contact.message"
      data-macro-type="attr-text"
    ></textarea>
  </label>
  <button type="submit" data-macro-key="contact.submit">Send message</button>
</form>

Editor behavior

  • Inline editors attach after login for attr-text, select, checkbox, and radio.
  • Clicking a field selects it for the overlay; typing updates draft payload.
  • Labels are often separate macro/text nodes so structure stays semantic (<label> + control).

Do

  • Keep name, action, and method in source control.
  • Give each editable control its own stable data-macro-key.
  • Mark button labels as text primitives when editors should change CTA wording.

Don’t

  • Don’t expect Macro to POST the form or validate server-side.
  • Don’t put secrets or payment card fields behind Macro keys.
  • Don’t reuse one key across multiple inputs.

See also Primitive reference and Editors · Form fields.