Rune Editor Compatibility Spec
This spec covers all remaining runes that need updates for editor compatibility. Three runes have already been updated: recipe, hero, and feature. This document covers everything else.
This spec covers all remaining runes that need updates for editor compatibility. Three runes have already been updated: recipe, hero, and feature. This document covers everything else.
The block editor needs three things from each rune to support visual editing:
data-name on structural elements — set via refs in createComponentRenderable (not data-field, which is for modifier properties consumed by the engine)editHints in engine config — maps each data-name value to an edit mode (inline, link, code, image, icon, none)data-field where data-name should be used; no manual data-rune on children (root gets it automatically via createComponentRenderable)| Mode | Behavior | Typical Use |
|---|---|---|
inline | Contenteditable with formatting toolbar | Headlines, blurbs, body text, list items |
link | URL + display text fields | Action buttons, CTA links |
code | Code editor popover | Terminal commands, code snippets |
image | File picker + alt text | Media, cover images, avatars |
icon | Icon picker gallery | Feature icons, decorative icons |
none | Not directly editable | Generated content, decorative elements |
See the already-updated runes for canonical examples:
runes/learning/src/tags/recipe.ts + runes/learning/src/config.ts) — editHints for inline content, images, structure badgesrunes/marketing/src/tags/hero.ts + runes/marketing/src/config.ts) — editHints for actions (link), commands (code), media (image)runes/marketing/src/tags/feature.ts + runes/marketing/src/config.ts) — editHints for definition items (icon, title, description)@refrakt-md/marketingrunes/marketing/src/tags/cta.ts)Current state: Has editHints and autoLabel in config already. Well-structured.
Changes needed:
editHints: { headline: 'inline', eyebrow: 'inline', blurb: 'inline', action: 'link', command: 'code' } and autoLabel with pageSectionAutoLabelStatus: DONE ✓
runes/marketing/src/tags/bento.ts)Current state: Has editHints and autoLabel for section-level fields. But manually creates meta tags with data-field for gap, columns, sizing (lines 191-193).
Changes needed:
data-field on meta tags (lines 191-193) with proper properties in createComponentRenderable so they flow through the standard modifier pipelineConfig editHints (already present): { headline: 'inline', eyebrow: 'inline', blurb: 'inline' }
Status: DONE ✓
runes/marketing/src/tags/bento.ts)Current state: No editHints, no autoLabel (only autoLabel: { name: 'title' } in config). Properties include name, size, span, icon. Refs include body, icon.
Changes needed:
{ title: 'inline', icon: 'icon' }body ref has appropriate data-nameStatus: DONE ✓
runes/marketing/src/tags/steps.ts)Current state: Has editHints and autoLabel for section-level fields.
Changes needed:
Status: DONE ✓
runes/marketing/src/tags/steps.ts)Current state: No editHints. Manually sets data-name='content' and data-name='media' on wrapper divs. Uses SplitLayoutModel.
Changes needed:
data-name assignments to refs in createComponentRenderable{ content: 'none', media: 'image' }Status: DONE ✓
runes/marketing/src/tags/pricing.ts)Current state: Has editHints and autoLabel for section-level fields. Manually sets data-layout and data-columns on ul element.
Changes needed:
data-layout and data-columns on the tiersList ul should be standard modifiers/propertiesStatus: DONE ✓
runes/marketing/src/tags/pricing.ts)Current state: No editHints. Properties include name (h1), description, price (p), currency (meta), url (anchor). Refs include body.
Changes needed:
name, price) from properties to refs so they get data-name instead of data-field{ name: 'inline', price: 'inline' }Status: DONE ✓
runes/marketing/src/tags/testimonial.ts)Current state: No editHints, no autoLabel. Critical issues:
data-field='author-name' and data-field='author-role' on created spans (lines 44, 55) — should use refs / data-nameChanges needed:
quote, authorName, authorRole, avatar from properties to refsdata-field assignments (lines 44, 55) — let createComponentRenderable handle via refsrating as property (modifier/meta value){ 'author-name': 'inline', 'author-role': 'inline', avatar: 'image', quote: 'inline' }Status: DONE ✓
runes/marketing/src/tags/comparison.ts)Current state: No editHints. Has pageSectionProperties for header. Complex postTransform.
Changes needed:
{ headline: 'inline', eyebrow: 'inline', blurb: 'inline' }Status: DONE ✓
runes/marketing/src/tags/comparison.ts)Current state: No editHints. Properties include name (span), highlighted (meta), row items. Refs include body.
Changes needed:
name from properties to refs so it gets data-name{ name: 'inline' }Status: DONE ✓
runes/marketing/src/tags/comparison.ts)Current state: No editHints. Properties include label (span), rowType (meta). Refs include body.
Changes needed:
label from properties to refs{ label: 'inline', body: 'inline' }Status: DONE ✓
@refrakt-md/docsrunes/docs/src/tags/api.ts)Current state: Has editHints. Properties include method, path, auth (meta tags). Refs include body. Config has structure with method (span), path (code), auth (span) structure entries.
Changes needed:
{ body: 'none', method: 'none', path: 'none', auth: 'none' } — structure elements are attribute-driven, not directly editableStatus: DONE ✓
runes/docs/src/tags/symbol.ts)Current state: Has editHints and autoLabel. Properties include kind, lang, since, deprecated, source. Refs include body, headline (via pageSectionProperties). Config has rich structure with kind-badge, lang-badge, since-badge, deprecated-badge, source-link.
Changes needed:
{ headline: 'inline', body: 'none', 'kind-badge': 'none', 'lang-badge': 'none', 'since-badge': 'none', 'deprecated-badge': 'none', 'source-link': 'link' }Status: DONE ✓
runes/docs/src/tags/symbol.ts)Current state: Has editHints. label in refs. Refs include label, body.
Changes needed:
label from properties to refs{ label: 'inline', body: 'none' }Status: DONE ✓
runes/docs/src/tags/symbol.ts)Current state: Has editHints. name in refs. Refs include name, body.
Changes needed:
name from properties to refs{ name: 'inline', body: 'none' }Status: DONE ✓
runes/docs/src/tags/changelog.ts)Current state: Has editHints and autoLabel. Properties include project, release items. Refs include releases.
Changes needed:
{ headline: 'inline', releases: 'none' }Status: DONE ✓
runes/docs/src/tags/changelog.ts)Current state: Has editHints. version moved to refs. Properties include date. Refs include version, body.
Changes needed:
version from properties to refs{ version: 'inline', body: 'none' }Status: DONE ✓
@refrakt-md/designrunes/design/src/tags/swatch.ts)Current state: No editHints. Inline rune (attributes only). Refs include chip, value. Properties include color, label, showValue.
Changes needed:
{ chip: 'none', value: 'none' } — attribute-driven, not content-editableStatus: DONE ✓
runes/design/src/tags/palette.ts)Current state: No editHints. Uses data-name extensively on generated elements for groups, swatches, scales. Properties include title, showContrast, showA11y, columns.
Changes needed:
data-name elements: { 'group-title': 'none', 'swatch-color': 'none', 'swatch-name': 'none', 'swatch-value': 'none', grid: 'none', scale: 'none' }'none'Status: DONE ✓
runes/design/src/tags/typography.ts)Current state: No editHints. Uses data-name extensively on generated specimens, sizes, weights. Properties include title, showSizes, showWeights, showCharset.
Changes needed:
{ title: 'none', specimen: 'none', specimens: 'none', sizes: 'none', weights: 'none', charset: 'none' }Status: DONE ✓
runes/design/src/tags/spacing.ts)Current state: No editHints. Uses data-name extensively on generated scale items, radii, shadows. Properties include title.
Changes needed:
{ title: 'none', section: 'none', scale: 'none', radii: 'none', shadows: 'none' }Status: DONE ✓
runes/design/src/tags/preview.ts)Current state: No editHints. Legacy issue: postTransform in config reads data-field attributes (data-field="source", data-field="themed-source") on lines 52, 59, 68 of runes/design/src/config.ts.
Changes needed:
data-field usage in postTransform to data-name pattern{ source: 'code' } — the preview source should be code-editabledata-field on pre elementssource and htmlSource from properties to refs in schemaStatus: DONE ✓
runes/design/src/tags/mockup.ts)Current state: No editHints. Refs include viewport. Properties include device, color, statusBar, label, url, scale, fit. PostTransform generates device chrome.
Changes needed:
{ viewport: 'none' } — content is the child markupStatus: DONE ✓
runes/design/src/tags/design-context.ts)Current state: No editHints. Uses data-name="title" and data-name="sections" manually. Properties include title, tokens, scope.
Changes needed:
{ title: 'none', sections: 'none' } — container for child design runesdata-name assignments to refs in createComponentRenderableStatus: DONE ✓
@refrakt-md/storytellingrunes/storytelling/src/tags/character.ts)Current state: No editHints. Properties include name, role, status, aliases, tags. Refs include portrait (optional), sections/body.
Changes needed:
name from properties to refs (visible span should use data-name){ name: 'inline', portrait: 'image', body: 'none', sections: 'none' }Status: DONE ✓
Current state: No editHints. AutoLabel { span: 'header' }. Properties include name. Refs include body.
Changes needed:
name from properties to refs{ header: 'inline', name: 'inline', body: 'none' }Status: DONE ✓
runes/storytelling/src/tags/realm.ts)Current state: No editHints. Properties include name, realmType, scale, tags, parent. Refs include scene (optional), sections/body.
Changes needed:
name from properties to refs{ name: 'inline', scene: 'image', body: 'none', sections: 'none' }Status: DONE ✓
Current state: No editHints. AutoLabel { span: 'header' }. Properties include name. Refs include body.
Changes needed:
name from properties to refs{ header: 'inline', name: 'inline', body: 'none' }Status: DONE ✓
runes/storytelling/src/tags/faction.ts)Current state: No editHints. Properties include name, factionType, alignment, size, tags. Refs include sections/body.
Changes needed:
name from properties to refs{ name: 'inline', body: 'none', sections: 'none' }Status: DONE ✓
Current state: No editHints. AutoLabel { span: 'header' }. Properties include name. Refs include body.
Changes needed:
name from properties to refs{ header: 'inline', name: 'inline', body: 'none' }Status: DONE ✓
runes/storytelling/src/tags/lore.ts)Current state: No editHints. Properties include title, category, spoiler, tags. Refs include body.
Changes needed:
title from properties to refs (visible span should use data-name){ title: 'inline', body: 'none' }Status: DONE ✓
runes/storytelling/src/tags/plot.ts)Current state: No editHints. Properties include title, plotType, structure, tags, beat items. Refs include beats.
Changes needed:
title from properties to refs{ title: 'inline', beats: 'none' }Status: DONE ✓
runes/storytelling/src/tags/plot.ts)Current state: No editHints. Properties include label, status, id, track, follows. Refs include body.
Changes needed:
label from properties to refs{ label: 'inline', body: 'none' }Status: DONE ✓
runes/storytelling/src/tags/bond.ts)Current state: No editHints. Uses data-name="connector" and data-name="arrow" manually. Properties include from, to, bondType, status, bidirectional. Refs include connector, body.
Changes needed:
from, to from properties to refs (visible spans){ from: 'inline', to: 'inline', connector: 'none', arrow: 'none', body: 'none' }Status: DONE ✓
runes/storytelling/src/tags/storyboard.ts)Current state: No editHints. Properties include panel items, variant, columns. Refs include panels.
Changes needed:
{ panels: 'none' }Status: DONE ✓
Current state: No editHints. Properties include image, caption. Refs include body.
Changes needed:
image from properties to refscaption from properties to refs{ image: 'image', caption: 'inline', body: 'none' }Status: DONE ✓
@refrakt-md/learningrunes/learning/src/tags/howto.ts)Current state: No editHints. Properties include estimatedTime, difficulty. Refs include header elements (via pageSectionProperties), tools, steps. Config has structure with meta-item entries.
Changes needed:
{ headline: 'inline', eyebrow: 'inline', blurb: 'inline', tool: 'inline', step: 'inline' }data-name on tool and step list items in schema (following recipe pattern)Status: DONE ✓
@refrakt-md/businessrunes/business/src/tags/cast.ts)Current state: No editHints. Uses pageSectionProperties for header. Properties include member items, layout. Refs include header, members.
Changes needed:
{ headline: 'inline', eyebrow: 'inline', blurb: 'inline', members: 'none' }Status: DONE ✓
Current state: No editHints. Properties include name (span), role (span). Refs include body.
Changes needed:
name, role from properties to refs{ name: 'inline', role: 'inline', body: 'none' }Status: DONE ✓
runes/business/src/tags/organization.ts)Current state: No editHints. Uses pageSectionProperties. Properties include type. Refs include headline, blurb, body.
Changes needed:
{ headline: 'inline', blurb: 'inline', body: 'none' }Status: DONE ✓
runes/business/src/tags/timeline.ts)Current state: No editHints. Uses pageSectionProperties. Properties include direction, entry items. Refs include headline, blurb, entries.
Changes needed:
{ headline: 'inline', blurb: 'inline', entries: 'none' }Status: DONE ✓
Current state: No editHints. Properties include date (time tag), label (span). Refs include body.
Changes needed:
date, label from properties to refs (visible elements){ date: 'inline', label: 'inline', body: 'none' }Status: DONE ✓
@refrakt-md/placesrunes/places/src/tags/event.ts)Current state: No editHints. Uses pageSectionProperties. Properties include date, endDate, location, url. Config has rich structure with detail, label, value, end-date, register refs.
Changes needed:
{ headline: 'inline', blurb: 'inline', body: 'none', detail: 'none', label: 'none', value: 'none', 'end-date': 'none', register: 'link' }Status: DONE ✓
runes/places/src/tags/itinerary.ts)Current state: No editHints. Uses pageSectionProperties. Properties include variant, direction, day items. Refs include headline, blurb, days.
Changes needed:
{ headline: 'inline', blurb: 'inline', days: 'none' }Status: DONE ✓
Current state: No editHints. AutoLabel { label: 'header' }. Properties include label, date, stop items. Refs include stops.
Changes needed:
{ header: 'inline', stops: 'none' }Status: DONE ✓
Current state: No editHints. AutoLabel { time: 'time', location: 'location' }. Properties include time, location, duration, activity, lat, lng. Refs include body.
Changes needed:
{ time: 'none', location: 'none', body: 'none' }Status: DONE ✓
runes/places/src/tags/map.ts)Current state: No editHints. Legacy issue: Config postTransform reads data-field attribute on children (line 84 of runes/places/src/config.ts). Properties include zoom, center, variant, height, provider, interactive, route, cluster, pin items. Refs include pins.
Changes needed:
data-field reads in config postTransform with findMeta helper pattern{ pins: 'none' } — map is web component–rendereddata-field on meta childrenStatus: DONE ✓
Current state: No editHints. Purely attribute-driven via parseLocationItem(). Properties include name, description, lat, lng, address, url, group. No refs.
Changes needed:
name, description from properties to refs (visible spans){ name: 'inline', description: 'inline' }data-field on name/description spansStatus: DONE ✓
@refrakt-md/mediarunes/media/src/tags/audio.ts)Current state: No editHints. Uses data-name='description' manually on div. Properties include waveform. Custom web component rendering.
Changes needed:
data-name to refs in createComponentRenderable{ description: 'inline' }Status: DONE ✓
runes/media/src/tags/playlist.ts)Current state: No editHints. Legacy issues:
data-field: 'id' on meta tag (line 190) — should use property attributedata-rune: 'track' on child track elements (line 131) — children should not have manual data-runeUses data-name for header, title, tracks, player.
Changes needed:
data-field: 'id' with data-name: 'id' on metadata-rune: 'track' on children — let identity transform handle typeof dispatch{ title: 'inline', header: 'none', tracks: 'none', player: 'none' }Status: DONE ✓
runes/media/src/tags/track.ts)Current state: No editHints. Uses data-name for track-name, track-artist, track-duration, track-meta, track-description. Properties include name, artist, duration, url, position, datePublished, type.
Changes needed:
{ 'track-name': 'inline', 'track-artist': 'inline', 'track-description': 'inline', 'track-duration': 'none', 'track-meta': 'none' }Status: DONE ✓
@refrakt-md/runes (Core)packages/runes/src/tags/hint.ts)Current state: No editHints. Config has structure with icon (ref) and title (ref, metaText) in header. Modifier: hintType.
Changes needed:
{ icon: 'none', title: 'none' } — structure-injected, attribute-drivenStatus: DONE ✓
packages/runes/src/tags/details.ts)Current state: No editHints. AutoLabel { summary: 'summary' }. Refs include body.
Changes needed:
{ summary: 'inline', body: 'none' }Status: DONE ✓
packages/runes/src/tags/accordion.ts)Current state: No editHints. AutoLabel includes pageSectionAutoLabel. Sections contentModel converts headings to accordion-item tags.
Changes needed:
{ headline: 'inline', eyebrow: 'inline', blurb: 'inline' }Status: DONE ✓
Current state: No editHints. AutoLabel { name: 'header' }. Refs include body.
Changes needed:
{ header: 'inline', body: 'none' }Status: DONE ✓
packages/runes/src/tags/tabs.ts)Current state: AutoLabel includes pageSectionAutoLabel. No explicit editHints.
Changes needed:
{ headline: 'inline', eyebrow: 'inline', blurb: 'inline' }Status: DONE ✓
Current state: No editHints. name already in refs (tabs.ts). image in properties.
Changes needed:
{ name: 'inline' }Status: DONE ✓
packages/runes/src/tags/codegroup.ts)Current state: Has editHints: { panel: 'code' }. Structure includes topbar with title ref.
Changes needed:
title: 'none' to editHints (structure-injected from attribute)Status: DONE ✓
packages/runes/src/tags/grid.ts)Current state: No editHints, no autoLabel. Modifiers: mode, collapse, aspect, gap, columns, padding, maxWidth, valign. Refs include cell.
Changes needed:
{ cell: 'none' } — cells contain other runesStatus: DONE ✓
packages/runes/src/tags/figure.ts)Current state: No editHints. Properties include caption, size, align. No refs.
Changes needed:
caption from properties to refs{ caption: 'inline' }Status: DONE ✓
Current state: No editHints. Modifiers: layout, lightbox, gap, columns. Refs include items.
Changes needed:
{ items: 'none' } — items are figure elementsStatus: DONE ✓
packages/runes/src/tags/showcase.ts)Current state: No editHints. Properties include shadow, bleed, aspect, offset, place. Refs include viewport.
Changes needed:
{ viewport: 'none' } — viewport wraps child contentStatus: DONE ✓
packages/runes/src/tags/embed.ts)Current state: No editHints. PostTransform handles URL detection and iframe generation. Refs include fallback.
Changes needed:
{ fallback: 'none' } — postTransform-generatedStatus: DONE ✓
Current state: No editHints. Modifiers: align, variant. Properties set in schema.
Changes needed:
{ body: 'inline' }Status: DONE ✓
Current state: No editHints. Modifiers: dropcap, columns, lead, align. Refs include body.
Changes needed:
{ body: 'none' } — content is the child textStatus: DONE ✓
Current state: No editHints. Modifiers: align, ratio, wrap. Refs include media, body.
Changes needed:
{ media: 'image', body: 'none' }Status: DONE ✓
Current state: No editHints. Modifier: variant. Refs include body.
Changes needed:
{ body: 'inline' }Status: DONE ✓
Current state: No editHints. Modifier: layout. Refs include panels.
Changes needed:
{ panels: 'none' } — panels contain child runesStatus: DONE ✓
Current state: No editHints. Custom contentModel converts blockquotes to messages. Refs include messages.
Changes needed:
{ messages: 'none' }Status: DONE ✓
Current state: No editHints. Modifier: align. Refs include body.
Changes needed:
{ body: 'inline' }Status: DONE ✓
Current state: No editHints. Modifier: variant. Refs include body, notes.
Changes needed:
{ body: 'none', notes: 'none' }Status: DONE ✓
Current state: No editHints. Refs include body.
Changes needed:
{ body: 'inline' }Status: DONE ✓
packages/runes/src/tags/datatable.ts)Current state: No editHints. Modifiers: searchable, sortable, pageSize, defaultSort. Refs include table.
Changes needed:
{ table: 'none' } — table is standard markdown tableStatus: DONE ✓
packages/runes/src/tags/form.ts)Current state: No editHints. Complex custom contentModel with type inference. Modifiers: variant, action, method, success, error, honeypot. Refs include body. PostTransform generates footer.
Changes needed:
{ body: 'none' } — form fields are complex custom contentModelStatus: DONE ✓
Current state: No editHints. AutoLabel includes pageSectionAutoLabel. Sections contentModel. Refs include steps.
Changes needed:
{ headline: 'inline', eyebrow: 'inline', blurb: 'inline', steps: 'none' }Status: DONE ✓
Current state: No editHints. Refs include body.
Changes needed:
{ body: 'none' }Status: DONE ✓
Current state: No editHints. Entirely postTransform-generated with data-name elements (line, gutter-num, gutter-prefix, line-content).
Changes needed:
{ line: 'none', 'gutter-num': 'none', 'gutter-prefix': 'none', 'line-content': 'none' } — all generatedStatus: DONE ✓
Current state: No editHints. Entirely postTransform-generated SVG.
Changes needed:
{ data: 'none' } — chart is generated from table dataStatus: DONE ✓
Current state: No editHints. PostTransform-generated.
Changes needed:
{ source: 'code' } — diagram source should be code-editableStatus: DONE ✓
Current state: No editHints. PostTransform-generated source panels.
Changes needed:
{ source: 'code' }Status: DONE ✓
Current state: No editHints. Structure includes header with title, meta, meta-item refs. PostTransform generates footer.
Changes needed:
{ title: 'none', meta: 'none', 'meta-item': 'none' } — all structure/attribute-drivenStatus: DONE ✓
Current state: No editHints. Processed entirely in postTransform.
Changes needed:
{ label: 'none', subtotal: 'none' }Status: DONE ✓
Current state: No editHints. Complex custom processing with headingsToList. NavItem uses data-field: 'slug' in schema.
Changes needed:
data-field: 'slug' is consumed by postTransform and removed from DOM (not a visible structural element); no editor benefit from changingStatus: DONE ✓ (no changes needed)
Current state: No editHints. Auto mode uses sentinel. Primarily generated content.
Changes needed:
{ items: 'none' }Status: DONE ✓
data-field in createComponentRenderableThe createComponentRenderable function itself (at packages/runes/src/lib/component.ts:34) sets data-field on properties. This is the standard behavior — properties are modifier/meta values consumed by the engine. The issue is when runes put visible, structural elements in properties instead of refs. The fix for each rune is to move visible elements to refs.
data-field in packages/runes/src/config.tsThe core config uses data-field reads in several postTransform helpers (lines 66, 147, 355, 772, 804, 873, 905). These are internal engine patterns for reading property metadata and may need separate assessment for whether they should migrate to a different attribute.
Many tests across all packages assert on data-field values. When runes are updated to use refs/data-name, corresponding tests must be updated. This is a significant portion of the work.
Recommended implementation order:
data-field issue