JORVEL

Polyglot monorepo

A JORVEL workspace can hold micro-frontends built with different frameworks — a React app, a Vue app, an Angular app — all federated into a single host. Each remote is embedded through the framework-neutral mount contract, so the host never imports a remote's framework. This is the real micro-frontend experience: independent teams, independent stacks, one running app.

Host is React; remotes are anything

The host owns the two-tier router and shell, so it's always React. Remotes are where the polyglot freedom lives — pick a framework per remote.

Generate apps by framework

jorvel generate remote asks which framework to use (in a TTY), or take it non-interactively with --framework:

bash
jorvel generate host shell                              # React host
jorvel generate remote dashboard --framework react     # React remote
jorvel generate remote pricing   --framework vue       # Vue 3 remote
jorvel generate remote reports   --framework angular   # Angular remote
jorvel generate remote widgets   --framework solid     # SolidJS remote
jorvel generate remote docs      --framework svelte    # Svelte 5 remote

jorvel federation      # wire every remote into the host
jorvel dev             # run the whole thing

Supported: react, vue, solid, svelte, angular. The interactive jorvel generate wizard asks per remote too.

Tailwind, per app

Each generate host/generate remote also prompts "Add Tailwind CSS?" (skip with --tailwind / --no-tailwind). Tailwind works for every framework — the scaffold wires PostCSS through rspack with a framework-correct contentglob, so one remote can use Tailwind while another doesn't.

What each remote gets

FrameworkExposed ./AppAdapter
ReactdefineReactRemote(Root)@jorvel/adapter-react
Vue 3defineVueRemote(Root)@jorvel/adapter-vue
SolidJSdefineSolidRemote(Root)@jorvel/adapter-solid
Svelte 5defineSvelteRemote(Root)@jorvel/adapter-svelte
AngulardefineAngularRemote(RootComponent)@jorvel/adapter-angular

Each scaffold ships a framework-appropriate rspack.config.mjs (correct loaders + Module Federation), a sample root component, a standalone dev entry that mounts the remote through the same contract the host uses, and jorvel.app.json marked with its framework.

Per-app + global AI skills

Every generated remote also gets a framework-specific skill at apps/<name>/.claude/skills/<fw>-remote.md — so a coding agent working in that app knows its conventions (Vue SFC + vue-loader, Angular standalone + JIT, Solid JSX via babel, …). The workspace-wide .claude/skills/mount-contract.md (from jorvel init) covers the cross-framework rules that apply everywhere.

text
my-app/
├── .claude/skills/mount-contract.md        # global — cross-framework rules
└── apps/
    ├── shell/          (react host)
    ├── dashboard/      .claude/skills/react-remote.md
    ├── pricing/        .claude/skills/vue-remote.md
    └── reports/        .claude/skills/angular-remote.md

Federation is framework-aware

jorvel federation shares each app's own framework runtime as a singleton — the React host + React remotes share react/react-dom; a Vue remote shares vue; an Angular remote shares @angular/*. The @jorvel/event-bus is shared across all apps as the neutral cross-app channel. A Vue remote never has React forced into its scope.

Talking between frameworks

There's no shared framework context across the boundary. Use the framework-neutral channels — the event bus or DOM CustomEvents:

ts
// Any remote, any framework
import { createEventBus } from '@jorvel/event-bus';
const bus = createEventBus();
bus.emit('cart:add', { sku: 'A1', qty: 2 });   // Vue remote
bus.on('cart:add', (p) => { /* … */ });          // React host reacts

Cost of going polyglot

Mixing frameworks means each ships its own runtime — a heavier baseline than an all-React workspace. Non-React scaffolds are an experimental starting point: the mount contract is stable, the build config is yours to tune. Reach for polyglot when you genuinely have mixed-stack teams; otherwise stay single-framework.