Skip to content

feat: scaffold React, Vue, Angular, and Nuxt apps from the CLI - #257

Merged
mridang merged 65 commits into
mainfrom
feat/cli-spa-frameworks
Jun 15, 2026
Merged

feat: scaffold React, Vue, Angular, and Nuxt apps from the CLI#257
mridang merged 65 commits into
mainfrom
feat/cli-spa-frameworks

Conversation

@mridang

@mridang mridang commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Adds setup --framework react|vue|angular|nuxt. Writes the SPA auth entry/pages and a dev proxy that forwards /__nextgen to the backend and attaches a sk_<project_id> bearer (from ZITADEL_PROJECT_ID) to the forwarded requests.

New file-writer ops: merge-vite-config (magicast, non-destructive) for React/Vue and merge-angular-proxy for Angular. Production still needs @zitadel/edge-proxy.

@vercel

vercel Bot commented Jun 11, 2026

Copy link
Copy Markdown

@mridang must be a member of the zitadel team on Vercel to deploy.
- Click here to add @mridang to the team.
- If you initiated this build, request access.

Learn more about collaboration on Vercel and other options here.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5ddb010489

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/lib/orca/patchers/rule/react/index.ts Outdated
Comment thread apps/cli/src/lib/orca/patchers/rule/vue/index.ts Outdated
Comment thread apps/cli/src/lib/orca/patchers/rule/angular/index.ts Outdated
Adds setup --framework react|vue|angular. Writes the SPA auth entry and a dev
proxy that forwards /__nextgen to the backend and injects the project secret on
/sessions/exchange. New file-writer ops: merge-vite-config (magicast) for
React/Vue and merge-angular-proxy for Angular.
@mridang
mridang force-pushed the feat/cli-spa-frameworks branch from 5ddb010 to 29c60fa Compare June 11, 2026 04:47
@vercel

vercel Bot commented Jun 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
nextgen Error Error Jun 15, 2026 2:56am

Request Review

Generalizes the edit op to a candidate-path list so the proxy merge finds
vite.config.{ts,mts,cts,js,mjs,cjs}. Adds a ViteSupport capability (shared
buildViteProxyOp) that React and Vue patchers implement, removing duplication.
Adds a Nuxt detector/scaffolder/patcher. Like Next, Nuxt proxies via server
middleware: the patcher registers @zitadel/sdk-nuxt through a non-destructive
nuxt.config.ts edit and writes login/register/profile pages plus plugins.
Extracts shared magicast helpers used by the Vite and Nuxt config edits.
Add braces to every single-line guard in the SPA/Nuxt config patchers and
emitted proxy templates. Resolve config files through a shared
configCandidates() helper so vite.config and nuxt.config both accept the full
ts/mts/cts/js/mjs/cjs set instead of a partial list. Raise E_VALIDATION when an
existing modules/transpile value is not an array instead of a raw TypeError.
The proxy implementation (PROXY_PATH, PROXY_ENTRY_CODE, viteProxyEdit) and the
FileOp wiring (ViteSupport, buildViteProxyOp) were split across two files but are
one concern; vite-support already imported viteProxyEdit, so no extra coupling.
Repoint the react/vue/angular template importers at vite-support.
PROXY_PATH (/__nextgen) is the shared proxy prefix every framework keys off, but
it lived in vite-support, so non-Vite patchers (Angular) imported it from a
Vite-named file. Move it to proxy.ts and drop the dead re-export in
react/templates.
The react/vue/angular/nuxt patchers each carried a copy of the CLI-version to
dist-tag helper. Replace all four with the shared npmDistTagForCliVersion from
public-cli, which also falls back to "latest" instead of "alpha" for a stable
CLI release. Next keeps its own helper: its fallback is the renderer's pinned
dependency version (workspace:* for the lit renderer), not a dist tag.
doctor --fix now reclaims edit ops, so a removed /__nextgen proxy in
vite.config/nuxt.config/angular.json is restored; the edits are idempotent.

nuxtConfigEdit routes its object descents through ensureEditableObject, which
throws a clean E_VALIDATION when runtimeConfig/build is not an inline object
literal instead of a raw magicast TypeError.

Replace the per-op overwrite flag with uniform conflict protection: the Angular
and Nuxt scaffolders now remove their starter entry files (as React/Vue already
did), so the patch writes into an absent path. Running setup on an existing app
no longer silently clobbers a user's App entry — it raises E_CONFLICT like the
Next patcher, recoverable with --force.
Wrap over-width single-line arrays/objects (Angular runCommand args, merge-env
entries, the magicast import) to the repo's 100-col Prettier style.
Extract parseConfigModule so the Vite and Nuxt edits drop their duplicated
let-mod try/catch. Rebuild the Next file/op lists immutably with conditional
entries + filter instead of push. Add a README to each patcher dir (next, react,
vue, angular, nuxt) describing what it writes and how its proxy reaches the
backend, in one shared format.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds multi-framework scaffolding/patching to the CLI’s Orca system so zitadel setup can create and integrate React (Vite), Vue (Vite), Nuxt, and Angular apps, including framework-specific auth entry files and dev-time /__nextgen proxy wiring via a new generic edit file operation.

Changes:

  • Added new scaffolders, detectors, and rule-based patchers for nuxt, react, vue, and angular, and registered them in the Orca registries.
  • Introduced a generic FileOp kind "edit" and executor support to enable non-destructive config edits (Vite/Nuxt via magicast; Angular via JSON edit).
  • Added framework templates/README docs plus unit tests for Nuxt config editing and Orca framework selection.

Reviewed changes

Copilot reviewed 38 out of 39 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
pnpm-lock.yaml Adds magicast@0.3.5 and associated lockfile updates.
apps/cli/package.json Declares magicast dependency for CLI config editing.
apps/cli/tests/unit/lib/orca/patchers/rule/reclaim.test.ts Extends reclaim tests to include new edit ops.
apps/cli/tests/unit/lib/orca/patchers/rule/nuxt/nuxt-config.test.ts Adds unit tests for Nuxt magicast config edit idempotency/validation.
apps/cli/tests/unit/lib/orca/index.test.ts Verifies Orca selects new scaffolders/patchers and lists frameworks.
apps/cli/src/lib/orca/scaffolders/vue.ts Adds Vue (Vite) scaffolder via create-vite.
apps/cli/src/lib/orca/scaffolders/react.ts Adds React (Vite) scaffolder via create-vite.
apps/cli/src/lib/orca/scaffolders/nuxt.ts Adds Nuxt scaffolder via nuxi init minimal template.
apps/cli/src/lib/orca/scaffolders/index.ts Registers new scaffolders in the scaffolder registry.
apps/cli/src/lib/orca/scaffolders/angular.ts Adds Angular scaffolder via Angular CLI.
apps/cli/src/lib/orca/patchers/rule/vue/templates.ts Adds managed src/App.vue template using @zitadel/sdk-vue.
apps/cli/src/lib/orca/patchers/rule/vue/README.md Documents Vue patcher behavior and dev proxy approach.
apps/cli/src/lib/orca/patchers/rule/vue/index.ts Implements Vue rule patcher + shared Vite proxy edit op.
apps/cli/src/lib/orca/patchers/rule/vite-support.ts Introduces shared Vite config proxy edit (magicast) and ViteSupport.
apps/cli/src/lib/orca/patchers/rule/reclaim.ts Makes doctor --fix reclaim config edit ops.
apps/cli/src/lib/orca/patchers/rule/react/templates.ts Adds managed src/App.tsx template using @zitadel/sdk-react.
apps/cli/src/lib/orca/patchers/rule/react/README.md Documents React patcher behavior and dev proxy approach.
apps/cli/src/lib/orca/patchers/rule/react/index.ts Implements React rule patcher + shared Vite proxy edit op.
apps/cli/src/lib/orca/patchers/rule/proxy.ts Centralizes the framework-agnostic /__nextgen proxy path constant.
apps/cli/src/lib/orca/patchers/rule/nuxt/templates.ts Adds managed Nuxt pages/plugins and SSR-safe auth seeding logic.
apps/cli/src/lib/orca/patchers/rule/nuxt/README.md Documents Nuxt patcher and server-middleware proxy behavior.
apps/cli/src/lib/orca/patchers/rule/nuxt/nuxt-config.ts Implements Nuxt config edit transform (magicast).
apps/cli/src/lib/orca/patchers/rule/nuxt/index.ts Implements Nuxt rule patcher with nuxt.config edit + templates.
apps/cli/src/lib/orca/patchers/rule/next/README.md Adds Next.js patcher README documenting what’s patched and proxy model.
apps/cli/src/lib/orca/patchers/rule/next/index.ts Refactors Next patcher op/path assembly to a filtered-array style.
apps/cli/src/lib/orca/patchers/rule/magicast-config.ts Adds shared magicast helpers for config editing and clean validation errors.
apps/cli/src/lib/orca/patchers/rule/file-writer/types.ts Extends FileOp union with new edit op type.
apps/cli/src/lib/orca/patchers/rule/file-writer/index.ts Adds executor support for edit (candidate resolution + idempotency + atomic write).
apps/cli/src/lib/orca/patchers/rule/config-paths.ts Adds shared config filename candidate generation (*.{ts,mts,cts,js,mjs,cjs}).
apps/cli/src/lib/orca/patchers/rule/angular/templates.ts Adds Angular managed root component, template, and proxy.conf.cjs.
apps/cli/src/lib/orca/patchers/rule/angular/README.md Documents Angular patcher behavior and dev proxy wiring.
apps/cli/src/lib/orca/patchers/rule/angular/index.ts Implements Angular rule patcher with angular.json edit + proxy conf.
apps/cli/src/lib/orca/patchers/rule/angular/angular-json.ts Implements Angular angular.json edit transform for proxyConfig/port.
apps/cli/src/lib/orca/patchers/index.ts Registers new patchers in the patcher registry.
apps/cli/src/lib/orca/detectors/vue.ts Adds Vue (Vite) detector.
apps/cli/src/lib/orca/detectors/react.ts Adds React (Vite) detector.
apps/cli/src/lib/orca/detectors/nuxt.ts Adds Nuxt detector.
apps/cli/src/lib/orca/detectors/index.ts Registers detectors and documents probe ordering to avoid mis-detection.
apps/cli/src/lib/orca/detectors/angular.ts Adds Angular detector.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

Comment thread apps/cli/src/lib/orca/patchers/rule/vite-support.ts Outdated
Comment thread apps/cli/src/lib/orca/patchers/rule/vite-support.ts Outdated
Comment thread apps/cli/src/lib/orca/patchers/rule/nuxt/nuxt-config.ts Outdated
Comment thread apps/cli/src/lib/orca/patchers/rule/angular/angular-json.ts
Comment thread apps/cli/src/lib/orca/patchers/rule/angular/templates.ts
Comment thread apps/cli/src/lib/orca/scaffolders/angular.ts
Comment thread apps/cli/src/lib/orca/patchers/rule/react/index.ts

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 63 out of 64 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment thread apps/cli/src/lib/orca/patchers/rule/nuxt/nuxt-config.ts Outdated
Comment thread apps/cli/src/lib/orca/patchers/rule/vite-support.ts Outdated
Add @zitadel/shared-component-styles and @zitadel/design-tokens to the Nuxt
build.transpile list, matching the repo's demo-nuxt config, so SSR builds don't
fail on their untranspiled ESM. Stop setting server.host in the Vite config
edit: it duplicated Vite's default and got in the way of opting into network
binding; the issuer/origin requirement is about the port, which is still set.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 63 out of 64 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment thread apps/cli/src/lib/orca/patchers/rule/vite-support.ts Outdated
Comment thread apps/cli/src/lib/orca/patchers/rule/angular/README.md Outdated
Read ZITADEL_PROJECT_ID via loadEnv(process.cwd()) instead of
dirname(fileURLToPath(import.meta.url)). Vite may bundle the config to a temp
file whose import.meta.url no longer points at the project root, leaving the
env unresolved; process.cwd() is Vite's own default env dir and reliably finds
.env.local. Drops the now-unused node:url/node:path imports. Also note the
package.json dev-script edit in the Angular patcher README.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 63 out of 64 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment thread apps/cli/src/lib/orca/patchers/rule/vite-support.ts
Comment thread apps/cli/src/lib/orca/patchers/rule/nuxt/nuxt-config.ts
viteProxyEdit and nuxtConfigEdit now track whether they actually add anything
and return the source untouched when nothing is missing, so the file-writer
skips the file instead of letting magicast reformat an already-patched config
on re-runs / doctor --fix. ensureArrayItem now reports whether it added the
item so the edits can detect a no-op.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 63 out of 64 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment thread apps/cli/src/lib/orca/patchers/rule/angular/templates.ts
Comment thread apps/cli/src/lib/orca/patchers/rule/angular/templates.ts

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 63 out of 64 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment thread apps/cli/SKILLS.md Outdated
--renderer is accepted for any framework and recorded in zitadel.json branding;
only the Next patcher varies its generated templates by it. "Next.js only"
overstated a restriction that doesn't exist and could mislead agents.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 63 out of 64 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment thread apps/cli/src/lib/orca/detectors/angular.ts
Comment thread apps/cli/src/commands/setup/index.ts
…ative

Fail fast with E_VALIDATION when an existing Angular project is older than 17,
since the generated templates use @if control flow that won't compile there.
Skip the DevPortPrompt when --dev-port was passed so an interactive answer
can't override the explicit flag.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 66 out of 67 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment thread apps/cli/src/lib/orca/patchers/rule/config-paths.ts
Probe *.cts/*.cjs after the ESM extensions so a project whose only config is
CommonJS is found, and reject CommonJS source (module.exports) in
parseConfigModule with a clear "convert to ESM or edit manually" message
instead of a misleading "file not found". configPattern still lists only the
editable ESM extensions.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 66 out of 67 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment thread apps/cli/src/commands/eject.ts Outdated
Comment thread apps/cli/src/lib/orca/patchers/rule/vite-support.ts Outdated
Comment thread apps/cli/src/lib/orca/patchers/rule/config-paths.ts Outdated
…mple

The eject manual step no longer calls the generic dev script "Zitadel". Fix the
configCandidates JSDoc example to show full filenames, and add the missing
"that" to the proxy-imports comment.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 66 out of 67 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment thread apps/cli/src/lib/orca/patchers/rule/vite-support.ts Outdated
Comment thread apps/cli/src/lib/orca/patchers/rule/nuxt/nuxt-config.ts Outdated
Comment thread apps/cli/src/lib/orca/patchers/rule/angular/index.ts
The Vite/Nuxt parse and CommonJS-rejection errors built their label from the
ESM-only configPattern, but the candidate list now also probes *.cjs/*.cts, so
a CommonJS-config error cited a glob that didn't include the offending file.
Use vite.config.* / nuxt.config.* labels (covering every candidate) and drop
the now-unused configPattern helper.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 66 out of 67 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment thread .changeset/cli-spa-frameworks.md
Comment thread apps/cli/src/lib/orca/patchers/rule/utils/magicast.ts Outdated
Match `module.exports =` rather than any mention of `module.exports`, so an
ESM config that references it in a comment or string isn't wrongly rejected as
CommonJS.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 66 out of 67 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment thread apps/cli/src/lib/orca/patchers/rule/utils/magicast.ts Outdated
Comment thread apps/cli/src/commands/eject.ts Outdated
…son eject step

Broaden the CommonJS detection to also match `exports.<name> =` (e.g.
`exports.default = ...`), so a CommonJS config using named exports is rejected
instead of getting ESM imports injected. Word the eject manual step for
angular.json specifically (remove the proxyConfig/port from the serve target)
rather than calling it a generic configuration block.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 66 out of 67 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment thread apps/cli/src/lib/orca/patchers/rule/utils/magicast.ts Outdated
Replace the raw-source regex with an AST walk that looks for a real top-level
module.exports / exports.x assignment, so module.exports appearing in a comment
or string literal in an otherwise-ESM config no longer trips a false positive.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 66 out of 67 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment thread pnpm-lock.yaml

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 66 out of 67 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment thread apps/cli/src/lib/orca/patchers/rule/react/README.md Outdated
Comment thread apps/cli/src/lib/orca/patchers/rule/vue/README.md Outdated
Comment thread apps/cli/src/lib/orca/patchers/rule/nuxt/README.md Outdated
The react/vue/nuxt READMEs only mentioned the framework-specific env var, but
the base patcher also writes ZITADEL_PROJECT_ID/ISSUER/URL/ENVIRONMENT (which
the dev proxy and Nuxt config read). Document those shared keys too.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 66 out of 67 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment thread apps/cli/src/lib/orca/patchers/rule/utils/magicast.ts Outdated
Comment thread apps/cli/src/lib/orca/patchers/rule/vite-support.ts
mridang added 2 commits June 14, 2026 19:39
# Conflicts:
#	apps/cli/README.md
#	apps/cli/src/commands/setup/index.ts
#	apps/cli/src/lib/orca/patchers/rule/next/index.ts
importIsPresent matched only the local identifier name, so a same-named import
from a different module (e.g. a loadEnv from elsewhere) would make the Vite
edit skip adding the real `import { loadEnv } from "vite"`. It now also matches
the source module when given, and the Vite call site passes the expected `from`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants