Getting started
JORVEL scaffolds a complete micro-frontend workspace in five commands. By the end of this guide you'll have a host, a remote, file-based routing, and a dev server with HMR running on the same origin.
Who is this for?
Prerequisites
- Node.js 20, 22, or 24 on Linux, macOS, or Windows — all three are supported and exercised in CI. The CLI uses
node:test/ nativefetch/structuredClone, so 18.x may work but is not covered. - pnpm 9.15+ is the supported package manager.
npm 10+andyarn 4+also work — see Troubleshooting if symlinks or workspace resolution misbehave. - A terminal that can run
npx/pnpm dlx, plusgitfor the generated project's default.gitignore/ GitHub Actions templates. - Optional but recommended: VS Code with the TypeScript and ESLint extensions. Generated projects ship a
.vscode/settings.jsonthat enables workspace-relative typing and ESLint-on-save.
What does "production-ready" mean here?
corepack enable
corepack prepare pnpm@9.15.5 --activate
# shorthand
pnpm create jorvel my-app
# or
pnpm dlx jorvel@latest init my-appRun in a terminal and init is interactive — it prompts for a template (host + remote · SaaS · blank), a package manager (pnpm / npm / yarn / bun), and Tailwind. Pass them as flags to skip the prompts:
npm create jorvel@latest my-app -- --template saas --pm pnpm --tailwind
# create-jorvel forwards every flag to `jorvel init`Try it in the browser
No install — open a starter in a StackBlitz sandbox and edit live:
Walkthrough
Create a running app
jorvel init scaffolds a complete, runnable app — the workspace (config, CI, deploy workflow, tooling) plus a starter React host + remote, already wired together. Like create-next-app: init, install, run. Add --tailwind for Tailwind; --no-app for a bare workspace.
pnpm dlx jorvel@latest init my-app
cd my-app
pnpm install
pnpm dev # host on :3000, loads the dashboard remote
# → apps/shell (host) + apps/dashboard (remote), federated + runningAdd more remotes — auto-wired
Each new remote is automatically configured into the host— federation config, host route table, and the host's REMOTES map all updated. Pick a framework + language at the prompt, or pass flags. No manual wiring.
jorvel generate remote pricing # interactive: framework? · js/ts? · Tailwind?
jorvel generate remote billing --framework vue --lang ts
# both are now mounted in the host at /pricing/* and /billing/* — just refreshRun the dev server
jorvel dev --proxy-remotes --hmr-remotes--proxy-remotesserves every remote on the host's origin so CSP, cookies, and SRI behave like production. --hmr-remotes reloads the host when a remote recompiles. Before launching, devchecks each app's port is free and fails fast (DEV-003) with the next free port if one is taken — skip with --no-port-check.
Add a route
Drop a file in apps/dashboard/src/pages/. JORVEL uses Next.js-style file conventions: index.tsx, [id].tsx, (group)/.
export default function Settings() {
return (
<main>
<h2>Settings</h2>
<p>Configure your account.</p>
</main>
);
}Re-scan with jorvel routes --watch. The host now matches /dashboard/settings.
Build for production
jorvel build # all apps
jorvel build --app shell # one appOutput lands under apps/<name>/dist/. Asset filenames carry content hashes; remoteEntry.js embeds SRI when federation.sri is on.
Deploy
jorvel deploy --target vercel
vercel deployThat's the whole flow.
Project layout
Every workspace follows the same conventions. Knowing where things live makes the rest of the docs read in any order.
my-app/
├── apps/
│ ├── shell/ # Host — owns "/", layout, auth chrome
│ │ ├── public/ # Static assets served by Rspack dev-server
│ │ ├── src/
│ │ │ ├── App.tsx # Root React component (used by both CSR + SSR)
│ │ │ ├── bootstrap.tsx # Client entry — calls getRouter()
│ │ │ ├── index.ts # async import of bootstrap (federation boundary)
│ │ │ └── jorvel.routes.ts # Auto-generated by 'jorvel routes'
│ │ ├── jorvel.app.json # App manifest: name, type, port, exposes
│ │ ├── jorvel.federation.json# Generated by 'jorvel federation'
│ │ └── rspack.config.mjs # Rspack + ModuleFederationPlugin
│ └── dashboard/ # Remote — owns "/dashboard/*"
│ └── src/
│ ├── remote.tsx # Exposed entry point (./App)
│ └── pages/ # File-based routes scanned by 'jorvel routes'
├── libs/ # Shared libraries (contracts, ui-kit, etc.)
├── jorvel.config.json # Workspace config: federation, security, deploy
├── pnpm-workspace.yaml # pnpm workspace declaration
├── tsconfig.base.json # Strict TS settings shared by every app
└── .github/workflows/ # CI: typecheck / lint / test / buildAnatomy of a request
Understanding what runs where saves hours when debugging. The dev-server walkthrough below traces a single page navigation end-to-end.
1. Browser hits the host
GET /dashboard/settings arrives at the Rspack dev-server on port 3000. The host serves index.html with its bootstrap chunk.
2. Host bootstraps
bootstrap.tsx calls getRouter() (singleton, StrictMode-safe) and mounts <RemoteOutlet routes remotes />. usePathname() returns /dashboard/settings.
3. Outlet matches the route
RemoteOutlet walks HOST_ROUTES, finds /dashboard/* → { remote: 'dashboard', module: './App' }, and triggers REMOTES.dashboard() — a native dynamic import('dashboard/App').
4. Federation loads the remote
Rspack's ModuleFederationPlugin fetches /jorvel/remotes/dashboard/remoteEntry.js (proxied to http://localhost:3001 by --proxy-remotes), bridges the React share scope, and resolves ./App.
5. Remote renders its sub-route
<RemoteApp subpath="/settings" pages={pages} /> matches settings.tsx from the generated jorvel.routes.ts, lazy-imports the chunk, and renders the page.
Daily commands cheat-sheet
The 80% of CLI flags you'll touch every day.
# Develop
jorvel dev --proxy-remotes --hmr-remotes # most common
jorvel routes --watch # in a second terminal, per remote
# Verify before pushing
jorvel typecheck # tsc --noEmit per package
jorvel lint # ESLint workspace-wide
jorvel test # Vitest, parallel
jorvel perf # bundle-size budgets
jorvel diagnose # env, ports, configs
# Ship
jorvel build # all apps, host first
jorvel build --app dashboard --compress # one app + gz/br
jorvel deploy --target vercel # writes vercel.jsonIf something breaks
- Run
jorvel diagnose. It checks Node, pnpm, Rspack versions, ports in use, generated federation configs, and React duplication risks. - Set
JORVEL_DEBUG=1in your shell to surface full stack traces from CLI errors. - See Troubleshooting for the most-hit issues (Invalid hook call, remote 404, hydration mismatch).
What's next?
Module Federation
Shared deps, allowlists, SRI, CDN public-path.
Security
Strict-dynamic CSP, SRI, base64url nonces.
Production checklist
Caching, observability, version checks.
Made it through the quickstart? Star the repo on GitHub.
