v0.17.0
Released June 2, 2026 · All releases
Declarative metadata & layout. The v0.17.0 milestone follows v0.16.0's registry-driven sites with a fully declarative model for how metadata-bearing and media-bearing runes are assembled — replacing per-rune imperative structure code with a small, orthogonal config vocabulary (metaFields + blocks + layout) and giving every rune a consistent, theme-overridable metadata treatment. It also lands the file-ref rune and the shared preview drawer.
Changes
- v0.17.0 — Declarative metadata & layout.
- A new, fully declarative model for how metadata-bearing and media-bearing runes are assembled — replacing per-rune imperative structure code with a small, orthogonal config vocabulary, and giving every rune a consistent metadata treatment. Additive: existing content keeps rendering; meta-bearing runes simply gain a cleaner, theme-overridable structure.
metaFields— a pure data manifest of a rune's meta-bearing fields (each declares itsmetaType,label,condition, sentiment, and any rich rendering). No layout, no placement.blocks— named metadata blocks projected frommetaFields, each a flat field list rendered by one layout primitive.layout— explicit, ordered placement of block names and content children per container (reservedrootkey for flat runes); unlisted content always appends, never drops.- A field's render shape is intrinsic to its
metaType— a chip (.rf-badge) forstatus/category/tag, bare inline text forid/quantity/temporal/code— independent of the block's layout. Themes override a rune'smetaFields/blocks/layoutby inner key. bar— a horizontal flex row of fields; per-fieldalign: 'end'pushes a field (and everything after) to the right edge,wraptoggles single-line.definition-list— labelled<dt>/<dd>rows in a responsive multi-column grid.{% bar %}and{% deflist %}— prose authoring handles that emit the same DOM as the projected primitives, for hand-authored rows and definition lists.- A single chip primitive —
.rf-badgeplus[data-meta-type]/[data-meta-sentiment]— is shared by the standalone{% badge %}rune and every chip-rendered field.data-meta-typecarries typography only (monospace forid/code, tabular-nums forquantity/temporal, primary color forid); geometry comes from the layout primitive and the badge class; sentiment drives color. href— render as a link (<a>), the named modifier holds the URL.rating— a filled-marks-out-of-total widget (stars, dots).icon— a leading glyph selected by the field's value (e.g. the hint header's note / warning / caution / check).renderWhenEmpty— gate on presence rather than truthiness, so a present-but-empty value still projects its block (e.g.{% codegroup title="" %}renders the window chrome without a filename).- Every meta-bearing first-party rune is migrated to the model: docs
api/symbol; learningrecipe/howto; storytellingcharacter/realm/faction/lore/plot; placesevent; mediaplaylist; marketingtestimonial; corebudget/codegroup/hint; and the plan entities. - Structure contracts (
refrakt contracts) now surface each projected block as an addressable element with its layout primitive and fields, and derive child order fromlayout. - The legacy
slots+structureconfig path still renders, but is superseded bymetaFields+blocks+layoutand emits a one-time migration warning. Its removal — and the removal ofRuneConfig.slots— is a breaking change planned for a later release; third-party plugins on the legacy path should migrate.projection(hide / group / relocate) andpostTransformremain as escape hatches.