Skip to content

feat: pluggable multi-framework renderers (Next.js, Vite, Astro)#96

Merged
PAMulligan merged 26 commits into
mainfrom
18-multi-framework-output-support-nextjs-vite-astro
May 29, 2026
Merged

feat: pluggable multi-framework renderers (Next.js, Vite, Astro)#96
PAMulligan merged 26 commits into
mainfrom
18-multi-framework-output-support-nextjs-vite-astro

Conversation

@PAMulligan
Copy link
Copy Markdown
Collaborator

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.

  • Three-axis model: outputTarget (language) × renderer (pluggable meta-framework) × appType (deployment shape). framework.type deprecated, folded into renderer with back-compat defaults.
  • Registry as single source of truth: renderers/<name>/renderer.json (schema-validated) + scripts/renderer-registry.js (list/resolve/detect, priority-ordered detection) + scripts/validate-renderer.js (wired into verify-all). 5 manifests: nextjs, vite, astro, sveltekit, expo.
  • Every consumer migrated to read the manifest: intake detection, Phase-4 converter dispatch, parallel-orchestration phase exclusion, token config, and TDD scaffolding — no remaining outputTarget/framework.type branching.
  • Net-new Astro: templates/astro/ (@astrojs/react + @astrojs/tailwind + Container-API tests) and .claude/agents/astro-converter.md (islands for interactive components via build-spec signals, static .astro otherwise).
  • setup-project.sh --renderer <name> (old flags aliased); new docs/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 5
  • bash scripts/verify-all.sh --include renderers,tokens — pass
  • bash scripts/check-doc-counts.sh — 54 agents / 20 skills, in sync
  • Reviewer: trace a renderer:"astro" build-spec end-to-end (detect → astro-converter dispatch → orchestration → token config → TDD)

Note: the repo-wide dead-code/knip check flags all standalone CLI scripts (including pre-existing agent-registry.js etc.); the new renderer scripts add to that pre-existing debt and are not a regression.

🤖 Generated with Claude Code

Paul Mulligan and others added 26 commits May 28, 2026 17:27
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>
@PAMulligan PAMulligan linked an issue May 28, 2026 that may be closed by this pull request
@PAMulligan PAMulligan self-assigned this May 29, 2026
@PAMulligan PAMulligan added enhancement New feature or request javascript Pull requests that update javascript code labels May 29, 2026
@PAMulligan PAMulligan added pipeline Figma/Canva-to-React conversion pipeline react React-specific functionality labels May 29, 2026
@PAMulligan PAMulligan moved this from Todo to Done in PMDS Open Source Roadmap May 29, 2026
@PAMulligan PAMulligan added this to the v2.0.0 milestone May 29, 2026
@PAMulligan PAMulligan merged commit 386ed72 into main May 29, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request javascript Pull requests that update javascript code pipeline Figma/Canva-to-React conversion pipeline react React-specific functionality

Projects

Development

Successfully merging this pull request may close these issues.

Multi-framework output support (Next.js, Vite, Astro)

1 participant