The Editor Integration Contract

What a theme must emit so the visual editor can select sections and blocks, preview edits live, and read finished out of the box.

The Editor Integration Contract#

The visual editor renders your theme through the same engine as the live storefront, plus a marker layer that makes things clickable. Most of the contract is automatic; three pieces are yours.

What the platform does automatically#

Marker

Injected by

Purpose

Section wrapper (data-tf-section-id)

Host, around every rendered page section

Maps a canvas click to the composition section. Layout-neutral (display: contents).

Theme-block markers

Host, around every {% blocks %} instance at every depth

Makes composed theme blocks selectable without any theme code.

Live edit transport

Editor runtime

Setting edits re-render the preview server-side over postMessage — no page reload, no theme JS involved.

What the theme must do#

1 — LOCAL block markers. Sections that iterate their own settings.blocks must wrap each block's output in {{ b._editor_block_open }} … {{ b._editor_block_close }}. These render as selection markers in the editor preview and as NOTHING on the live storefront. A local block without markers renders fine but cannot be clicked in the editor.

vein
{% for b in settings.blocks %}
  {% unless b.disabled == true %}
    {% if b.type == 'quote' %}
      {{ b._editor_block_open }}
      <blockquote>{{ b.settings.text }}</blockquote>
      {{ b._editor_block_close }}
    {% endif %}
  {% endunless %}
{% endfor %}

2 — FIELD targets. data-tf-field="" on an element lets the editor scroll/highlight it when the matching input focuses in the inspector. Optional, but the difference between a good and a great editing feel.

3 — EDITOR-ONLY affordances. {{ b._editor_block_open }} is truthy only in the editor preview — branch on it for editor-only placeholders, like a clickable stub for a menu block whose menu is not picked yet. Never ship merchant-visible hints to the live storefront.

vein
{% if settings.menu_resolved.items.size == 0 and b._editor_block_open %}
  {{ b._editor_block_open }}<div class="menu-empty">{{ settings.menu_empty_hint }}</div>{{ b._editor_block_close }}
{% endif %}

Read finished out of the box#

Every section must look designed BEFORE the merchant configures it: placeholder art via {{ 'product-1' | placeholder_svg }} where an image is unpicked, placeholder cards where a list is empty, a placeholder card for an unpicked product spotlight. Placeholders render on the live storefront too — a fresh store looks intentional, never broken. A section whose defining feature is invisible until configured fails review.

Diagnosing editor issues: theme or platform?#

Symptom

Whose bug

Clicking a section selects the WRONG section in the sidebar

Platform (selection routing)

Clicks land visually offset / wrong element highlights

Theme (overlapping/absolute markup swallowing the click)

A local block cannot be selected at all

Theme (missing {{ b._editor_block_open }} markers)

Focusing an inspector input does not highlight the canvas

Theme (missing data-tf-field)

A theme-block (composed) instance cannot be selected

Platform (host injects those markers)

Edit does not appear in preview until save

Platform (report it — the preview must always track unsaved edits)