Getting started
React versions
^18.3.0 || ^19.0.0); new projects start on React 18. The roadmap records this as finding U11 (fixed in 0.3.2).The quickest way to a working project is the create-devora installer. It works from an empty directory — you don't need a devora.config.ts or any framework files first.
npm create devora@latest
Yarn and pnpm work the same way: yarn create devora or pnpm create devora (npx create-devora@latest does too). You need Node 20 or newer. New projects depend on @devorajs/core and @devorajs/cli ^0.3.5 and start on React 18.
On a recent npm (11), the install can print a warning that esbuild's postinstall script is not yet covered by allowScripts; install, devora dev and devora build still work, and the warning comes from npm, not from Devora.js.
What it asks
Run with no flags in a real terminal, it prompts for four things in order:
1. Project name. Defaults to my-devora-app. This becomes the directory the CLI creates — it refuses to run if that directory already exists.
2. What do you need? full-stack (the default) generates page apps plus one shared backend, packages/backend. frontend generates page apps only, with no packages/backend at all. backend generates API-only apps — an endpoints/ folder of routes, served under /api, with no pages and no React — plus the shared backend. Either way a project gets at most one shared backend; logic only one app needs can live inside that app instead (see The shared backend pattern).
3. App names (comma-separated). Defaults to marketing,dashboard,admin (api for a backend-only project). Each name becomes one app under apps/ — this is where multi-app is decided. A single-app project just answers with one name; a project with a public site, a logged-in product, and an internal panel answers with three. You can add or remove apps later with devora add/devora remove, so this choice isn't permanent.
4. Auth mode, once per app. For each app name, it asks: "Does <app> need auth/sessions? [shared/isolated/none] (default: shared)". This is the per-app choice described in Core concepts — shared puts the app on the project's common login/session, isolated gives it its own separate sessions — its own cookie name and optionally its own secret, so a login to one app is never valid in the other (e.g. an admin panel with a different identity provider), and none disables sessions and CSRF for that app entirely (e.g. a marketing site with no login anywhere). A marketing-style app should answer none — it never generates a login route or expects a session secret.
Every prompt has a non-interactive fallback: running in a script or CI (no real TTY) skips straight to the defaults above, and --scope=fullstack|frontend|backend, --apps= and --auth=name:mode,... flags let you skip the prompts entirely while scripting a scaffold. --pm=npm|pnpm|yarn picks the package manager (otherwise it's the one you ran the installer with) and --skip-install only writes the files:
npm create devora@latest my-app -- --scope=fullstack --apps=site,app --auth=site:none,app:shared --pm=npm
Resulting project structure
For the default answers (full-stack, three apps, all shared auth), you get:
my-devora-app/
├── devora.config.ts # declares every app + the project-wide auth default
├── package.json # dev / dev:host / build / start / typecheck scripts
├── tsconfig.json, tsconfig.base.json
├── .env.example # the session secrets production needs
├── packages/
│ └── backend/ # the shared backend — server functions + your DB client
│ └── db/index.ts # stub: plug your own database in here
└── apps/
├── marketing/
│ ├── routes/ # index.tsx, plus login/logout/account.tsx for an app with auth
│ ├── error.tsx # the app's 404 and error page
│ ├── app.config.ts # apiDir: "endpoints", sitemap, head
│ ├── vite.config.ts
│ ├── entry-server.tsx, island-client.tsx, csr-client.tsx
│ ├── package.json, tsconfig.json
│ └── vercel.json, netlify.toml
├── dashboard/ # same layout
└── admin/ # same layoutEach app scaffolded with shared or isolated auth also gets a login.tsx/logout.tsx route pair and a protected demo route (account.tsx), wired up to the sessions described in Security model. An app scaffolded with none gets only index.tsx — no login routes, no session dependency. The assets/ folder (logo, favicon) and a few config files (pnpm-workspace.yaml, .gitignore, .npmrc, a README.md) sit at the project root too. API routes for a page app go in an endpoints/ folder you create when you need one (apiDir in app.config.ts); they're served under /api. Not api/: on Vercel a top-level api/ folder is Vercel's own functions folder (see Deployment).
A frontend project is the same minus packages/backend. A backend project has packages/backend and API-only apps instead:
my-devora-app/
├── devora.config.ts
├── package.json
├── packages/
│ └── backend/
│ └── db/index.ts
└── apps/
└── api/
├── endpoints/ # health.ts, plus session.ts (token login/logout) and me.ts for an app with auth
├── app.config.ts # backendOnly: true, apiDir: "endpoints"
├── vite.config.ts
├── package.json, tsconfig.json
└── vercel.json, netlify.tomlNext steps: start the dev server
From inside the project, after the installer's dependency install has finished (or after you've run npm install yourself):
cd my-devora-app npm run dev
That starts every app in dev mode and prints a short header with the CLI version and how long startup took, every app's URLs, then each app's routes (pages always; API routes listed up to 10 per app, counted above that). Ports start at 10000, one per app in devora.config.ts order. To run a single app, pass the flag through npm: npm run dev -- --app=dashboard. --routes lists every API route, --quiet prints only the URLs, warnings and errors, and npm run dev:host exposes the dev servers on your local network (with a warning). .env files in the project root are loaded automatically.
Why not just devora dev? The CLI is installed into the project (node_modules), not onto your system PATH — so a bare devora command isn't found. That's normal: Next.js, Vite, and most framework CLIs work exactly the same way. It also means every project runs the exact CLI version it pins. Your options:
| Command | Notes |
|---|---|
npm run dev | Recommended. Runs the project's dev script, which calls its own pinned CLI. It's what the installer prints, and it can never pick up the wrong package. Other commands are scripts too: npm run build, npm run start, npm run dev:host. |
npx devora dev | Also runs the project's own CLI, for any command without a script (e.g. npx devora list). Only inside the project, after npm install: anywhere else, npx looks up the npm package literally named devora, which is an unrelated third-party tool — decline if npx offers to install it. |
npm install -g @devorajs/cli | Makes a bare devora command available everywhere. A convenience tradeoff, not the recommended default: the global copy doesn't follow each project's pinned version, so it can drift out of sync with the CLI a given project was built and tested against. |
See the CLI reference for every command, or go straight to Build your first feature for a complete worked example.