Acceptance Criteria
- New
packages/vue/ package exists with @refrakt-md/vue name - Exports a
Renderer component that recursively renders a RendererNode tree - Renderer dispatches on
typeof attribute to select registered component overrides (falls back to generic HTML element) - Uses
extractComponentInterface from @refrakt-md/transform to partition children into properties, refs, and anonymous content - Property values passed as named Vue props to component overrides
- Top-level refs passed as Vue named slots
- Original
tag object passed as prop alongside extracted props (hybrid per ADR-008 Option 4) - Exports a component registry mechanism (similar to
@refrakt-md/svelte's registry) - Exports an
elements override mechanism for HTML element-level overrides (Table, Pre, etc.) - Nuxt adapter can use the Vue renderer instead of
renderToHtml() for pages with component overrides - TypeScript compiles cleanly
- Test suite covers extraction, dispatch, and fallback rendering
Approach
Mirror the architecture of @refrakt-md/svelte:
Renderer.vue — recursive component that walks the renderable treeregistry.ts — typeof name → Vue component mappingelements.ts — HTML element name → Vue component mapping (for Table, Pre, etc.)theme.ts — VueTheme interface (manifest + layouts + components + elements)
Vue has native named slots, making it the most natural fit after Svelte. The renderer uses <component :is> for dynamic dispatch with v-bind for props and <template #name> for named slot content.
The extraction logic is already framework-agnostic (extractComponentInterface in @refrakt-md/transform). The Vue-specific work is:
- Converting extracted refs into named slot content via Vue's
<template #name> syntax - Passing scalar props via
v-bind - Recursive rendering with
<component :is> for dynamic dispatch
References
- ADR-008 — Framework-native component interface for rune overrides
- WORK-117 — Framework-agnostic extraction logic (done)
- WORK-119 — Svelte renderer extraction (done, reference implementation)
packages/svelte/src/Renderer.svelte — Svelte renderer (reference)packages/nuxt/ — Nuxt adapter (consumer of this package)
Resolution
Completed: 2026-04-06
Branch: claude/implement-spec-030-F0LFn
What was done
- Created
packages/vue/ with full ADR-008 component interface Renderer.ts — Vue 3 defineComponent using h() render function for recursive tree rendering- Component overrides dispatched via data-rune, receiving:
- Properties as named Vue props
- Named refs as Vue named slots (pre-rendered HTML via innerHTML)
- Anonymous children as default slot
- Original tag as escape-hatch prop
- Element overrides: Table (scrollable wrapper), Pre (rf-codeblock structure)
- Registry + elements + VueTheme type exports
- 20 tests using
@vue/server-renderer SSR rendering
Notes
- Used
defineComponent + h() render functions instead of .vue SFC to avoid needing vue-tsc/vite in the build - Named slots use Vue's native slot mechanism:
h(Component, props, { slotName: () => vnode }) - All 2022 tests pass (20 new)