Acceptance Criteria
packages/astro/ supports registering .astro component overrides keyed by typeof name- Renderer dispatches on
typeof attribute to select registered .astro component overrides (falls back to identity-transformed HTML) - Uses
extractComponentInterface from @refrakt-md/transform to partition children - Property values passed as Astro props (
Astro.props.prepTime, etc.) - Top-level refs passed as Astro named slots (
<slot name="headline" />, <slot name="ingredients" />) - Original
tag object passed as prop alongside extracted props (hybrid per ADR-008 Option 4) - Component registry mechanism added to
@refrakt-md/astro (e.g., registry.ts) - Integration hook wires up the registry so components are available at render time
- TypeScript compiles cleanly
- Test suite covers extraction, dispatch, and fallback rendering
Approach
Unlike React/Vue renderers which are recursive components, the Astro renderer operates at build time during SSR. The approach is:
- Component registry — export a
registry map of typeof name → .astro component, similar to @refrakt-md/svelte's registry - Render phase — when rendering a node with a
typeof that matches a registered component, use extractComponentInterface to partition children, then render the .astro component with props and named slots - Fallback — unregistered runes render via identity-transformed HTML as today
Astro's native named slots make this particularly clean:
---
const { prepTime, difficulty } = Astro.props;
---
<article class="my-recipe">
<slot name="headline" />
<slot name="ingredients" />
<slot name="steps" />
</article>
The main complexity is integrating the component dispatch into Astro's rendering pipeline, which differs from Svelte/React/Vue's recursive component model.
References
- ADR-008 — Framework-native component interface for rune overrides (see Astro special case in Consequences)
- WORK-117 — Framework-agnostic extraction logic (done)
- WORK-119 — Svelte renderer extraction (done, reference implementation)
- WORK-123 — React renderer (for island components)
- WORK-124 — Vue renderer (for island components)
packages/astro/ — Astro adapter (this package gets the additions)
Resolution
Completed: 2026-04-06
Branch: claude/implement-spec-030-F0LFn
What was done
RfRenderer.astro — recursive Astro component that dispatches on data-rune to registered component overrides- Component overrides receive extracted properties as Astro props, named refs as native Astro named slots (
<Fragment slot="name" set:html={html} />), anonymous children as default slot, and original tag as escape-hatch prop - Element overrides:
Table.astro (scrollable wrapper) and Pre.astro (rf-codeblock structure) registry.ts — ComponentRegistry type + empty default, exported from index.ts- Package.json exports for
./RfRenderer.astro and ./elements/*.astro - Removed stale
themeAdapter reference from integration hook (per ADR-009) - 8 tests covering registry, extraction pipeline, and dispatch logic
Notes
.astro components shipped as source (not compiled), matching the existing BaseLayout.astro pattern- Actual Astro component rendering can't be tested in vitest — tests cover the TypeScript extraction pipeline that
RfRenderer.astro depends on - For interactive runes in Astro islands, the island's framework renderer (React/Vue/Svelte) handles extraction per WORK-123/124/119