v0.16.0
Released May 29, 2026 · All releases
Registry-driven sites. v0.16.0 turns the entity registry into pages and listings declaratively, delivers the three sibling registry-query runes (collection / relationships / aggregate — items / edges / numbers), and proves the system by scaffolding a real plan site from refrakt's own plan/ content. Builds directly on v0.15.0's embedding primitives (ref / expand).
Changes
- v0.16.0 — Registry-driven sites.
- Turns the entity registry into pages and listings declaratively, ships the three sibling registry-query runes (
collection/relationships/aggregate— items / edges / numbers), and proves the system by scaffolding refrakt's own plan site from theplan/content tree. {% collection %}(SPEC-070) — the plural counterpart toref/expand. Queries the registry withtype+filter, appliessort/group/limit, and projects entities intolist/grid/tablelayouts. Per-item body templates with$itembound; heading-delimited table columns; shared field-match grammar; shared formatter functions (humanize,date,number,currency,join); 3-zone body (preamble / template / fallback) with$count/$shownbindings;group-display="accordion"for collapsible groups.{% relationships %}(SPEC-072) — graph-edge counterpart tocollection. Renders an entity's edges grouped by kind (or type), generic over any domain's relationship vocabulary. Shares$itemsemantics withcollectionso card partials are reusable across both. Domain-aware ordering, accordion group display, body zones for empty state.{% aggregate %}(SPEC-076) — number-projecting sibling. No-body form ({% aggregate type="work" filter="status:done" /%}) renders a single inline integer; body-zoned form iterates groups with$itembound to{ key, count, value, percent, total, shown }. Optionalvaluesub-filter (e.g.value="status:done") drives$item.percentfor progress-bar ratios without a second query.- Plugin-contributed routes (SPEC-069) — new
contributePagespipeline phase plus declarativeentityRoutesinrefrakt.config.jsonthat generate one page per registered entity matchingtype+ optionalfilter.embed()embeddability contract for cross-page composition. - Plan site scaffolding (SPEC-071) — refrakt's own plan site rebuilt from
plan/viaentityRoutes+ the registry-query runes. The bespokeplan build/plan servecommands are retired. Dashboard composition (aggregate header summary + per-statuscollectionpanels + empty-statehintrunes) shipped as the canonical scaffold template. - Theme toggle (SPEC-073) — light / dark / auto toggle as both a chrome slot and a
{% theme-toggle /%}rune, with shared behavior and prod-build CSS parity for the Cloudflare-style no-runes-bundle. - Accordion polish — leading rotating chevron via SVG mask, native
<details>slide animation via::details-content+interpolate-size, dividers-only outer treatment. - Badge restyle to a compact sentiment-tinted chip; sentiment via
color-mix(in srgb, var(--meta-color) X%, transparent). - New "Registry" category in the rune catalog for the cross-page-query runes (
xref/expand/collection/relationships/aggregate); seven previously-missing runes added to the catalog (xref,badge,gallery,showcase,bg,tint,blog). refrakt.config.jsonschema —themeis nowstring | SiteThemeConfig(was juststring); newSiteThemeConfigdefinition withpackage,presets,tokens,modes, andcode.colorScheme.highlightflagged as legacy in favour oftheme.presets(Lumina syntax presets contributing--rf-syntax-*overrides) +theme.code.colorScheme(forced light/dark code).site/content/runes/aggregate.md— full reference page with live previews; sites.md updated for the theme object form.- Nav items containing an inline
{% badge %}now sit as a flex row so the badge rides alongside the link instead of wrapping under it (link'sdisplay: blockwas claiming the full row). - Mobile docs toolbar long page titles now ellipsise instead of forcing horizontal page scroll (
flex: 1 1 0+max-width: 100%; overflow: hidden;on the toolbar). - Conversation rune's
speakers="A,B"attribute now renders names as bold-inline prefix inside the bubble, matching the explicit> **Name**:form. Two related issues fixed: the extractor was missing the Markdocinlinewrapper around paragraph content, and the fallback path didn't inject a strong-prefix. The speaker-carrier span is now hidden via the correctdata-field="speaker"selector.