feat: pluggable multi-framework renderers (Next.js, Vite, Astro)#96
Merged
PAMulligan merged 26 commits intoMay 29, 2026
Merged
Conversation
Add the approved design for abstracting code generation into pluggable renderer manifests (nextjs, vite, astro, sveltekit, expo), a renderer registry, registry-driven detection/dispatch, and a net-new Astro hybrid (.astro + React islands) converter. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Six-phase TDD plan: schema+registry+validator, author 5 manifests + CI wiring, migrate detection, migrate dispatch/orchestration/token/TDD consumers, net-new Astro template+converter, then docs/count sync. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…le detect tie-break Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ed sniffing Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace hardcoded outputTarget-to-agent dispatch in the three build-from-* commands with reading the build-spec renderer field and resolving its manifest via renderer-registry.js. Phase 4 now dispatches manifest.converter, preferring the source-appropriate React converter (figma/screenshot -> figma-react-converter, canva -> canva-react-converter) when language is react. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace per-framework phase-skipping with a Step 0 that resolves the build-spec renderer manifest and drops every phase listed in manifest.phases.exclude before building the dependency graph (e.g. expo excludes visual-diff/cross-browser/responsive/dark-mode). The component-build dispatch row now selects the converter from the manifest instead of outputTarget. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Both token skills now resolve the build-spec renderer manifest and choose the config target from manifest.language (react/vue/svelte -> Tailwind CSS-var approach; react-native -> NativeWind) and manifest.template (config location). Astro reuses the React/Tailwind path. Token-extraction logic is unchanged; only the framework-target selection moved from outputTarget branching to the manifest. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the outputTarget -> test runner/library mapping with reading manifest.test (runner, library, setup, containerApi) from the resolved renderer manifest. Add a forward-looking Astro test split (islands -> Vitest + RTL, static .astro -> Vitest + Container API, page interactivity -> Playwright E2E) for when the astro manifest is authored. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Follow-up to the Phase-4 renderer dispatch refactor: the build-from-screenshot Storybook (4.5) skip note referenced 'react-native outputTarget'. Reword to the renderer-driven framing (skip when the renderer has no browser story, e.g. expo). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ner-api tests) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add .claude/test-fixtures/astro-hybrid.build-spec.json documenting the island/static split contract (one interactive component with a behavioral action -> React island + client:* directive; one static presentational component -> zero-JS .astro). Extend renderer-registry.test.js to assert the fixture is valid JSON, encodes the island/static split, and resolves its renderer to astro-converter via the real registry. Also align verify-all.test.js with the renderer system's CI wiring: the agent-plugins and renderers checks were added to verify-all.sh without updating the expected check count (9->10) and skip count (7->8), leaving the suite red. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…re annotations Adds @testing-library/user-event to the astro template for parity with the React sibling templates (the astro-converter agent's island tests use userEvent). Documents that the astro-hybrid fixture's underscore fields are test annotations, not converter inputs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a --renderer <name> option to setup-project.sh that validates the name against renderer-registry.js, resolves the manifest, and copies the manifest.template plus templates/shared into the new project. Existing framework flags become aliases (--next→nextjs, --vite→vite, --expo→expo, --svelte→sveltekit); --react and --vue retain their prior behavior. Astro is now reachable via --renderer astro and the interactive menu. Usage text and a new --dry-run plan path source the renderer list from the registry, and a test covers astro, the --next/--svelte aliases, unknown renderers, and the legacy --react path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add docs/multi-framework/renderers.md covering the three-axis model (outputTarget = language, renderer = pluggable meta-framework, appType = deployment shape), the full manifest field reference, the renderer-registry.js CLI (list/resolve/detect) and validate-renderer.js, the outputTarget-only back-compat rule, the Astro hybrid model as a worked example, and a how-to-add-a-renderer checklist. Link it from the multi-framework README. In CLAUDE.md, add the renderer-registry and validate-renderer scripts to both script reference sections and note the renderers/ directory in the project structure. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bump script count for renderer-registry.js + validate-renderer.js and note the 5 pluggable renderers (nextjs, vite, astro, sveltekit, expo). Agent count (54) was synced when astro-converter landed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a new renderer axis to the design-to-code pipeline, abstracting code generation into declarative, pluggable manifests resolved by a registry. Adds Astro as a net-new output target (hybrid: zero-JS
.astro+ React islands) and formalizes Next.js/Vite/SvelteKit/Expo as first-class renderers.outputTarget(language) ×renderer(pluggable meta-framework) ×appType(deployment shape).framework.typedeprecated, folded intorendererwith back-compat defaults.renderers/<name>/renderer.json(schema-validated) +scripts/renderer-registry.js(list/resolve/detect, priority-ordered detection) +scripts/validate-renderer.js(wired intoverify-all). 5 manifests: nextjs, vite, astro, sveltekit, expo.outputTarget/framework.typebranching.templates/astro/(@astrojs/react + @astrojs/tailwind + Container-API tests) and.claude/agents/astro-converter.md(islands for interactive components via build-spec signals, static.astrootherwise).setup-project.sh --renderer <name>(old flags aliased); newdocs/multi-framework/renderers.md; agent count synced to 54.Design + plan:
docs/plans/2026-05-28-multi-framework-renderers-design.md,docs/plans/2026-05-28-multi-framework-renderers.md.Test Plan
pnpm vitest run --config scripts/__tests__/vitest.config.js— 30 files, 396 tests pass (registry list/resolve/detect+precedence, validator, astro fixture contract, setup-project flag/aliases)node scripts/validate-renderer.js --all --json— ok, count 5bash scripts/verify-all.sh --include renderers,tokens— passbash scripts/check-doc-counts.sh— 54 agents / 20 skills, in syncrenderer:"astro"build-spec end-to-end (detect → astro-converter dispatch → orchestration → token config → TDD)🤖 Generated with Claude Code