ZitadelDocs

Quickstart

Add the Zitadel preview to a local app with the alpha CLI and npm-binary runtime.

Use this path when you want to add Zitadel auth to a local app without a source checkout.

Prerequisites

  • Node.js 24 or newer.
  • A package manager supported by your app.
  • Docker only if you intentionally choose the Docker runtime backend.

Create or enter an app directory

mkdir myapp
cd myapp

Check prerequisites

npx @zitadel/cli@alpha doctor

Before setup, doctor checks local runtime prerequisites. After setup, it also verifies generated app files and local config.

Start local Zitadel

npx @zitadel/cli@alpha start

By default this starts the matching @zitadel/server npm binary for the alpha train and stores runtime metadata under .zitadel/local/runtime.json. Runtime data is stored under .zitadel/local/nextgen-data (SQLite by default, see Databases).

start also creates a local admin, admin@zitadel.localhost, and ends by printing a one-time sign-in link for the management console. Keep it: it is how you reach the console without a password. You can print a fresh one at any time with zitadel console.

Scaffold auth

npx @zitadel/cli@alpha setup --server local

Run setup in the directory start ran in, or one inside it: setup looks there for the local admin, and without it the project is not attached to a team and the console does not list it.

In a fresh directory, setup asks which framework to scaffold. Scripted runs should pass --framework next, --framework nuxt, --framework react, --framework vue, or --framework angular.

Setup also asks how users should sign in and scaffolds the matching schema and login flow: --preset password-first (the default: email + password, passkey optional during registration) or --preset passkey-first (a one-tap passkey up front, with an email + password fallback). The preset only picks the starting point — everything under .zitadel/ stays editable.

Setup writes the app files, .env.local, zitadel.json, and .zitadel/**, then installs dependencies with the detected package manager unless --skip-install is passed.

Against a local server, setup by default also attaches the project to the local admin's team and prints Project owned by admin@zitadel.localhost (team ...). The project is owned from the start, so there is nothing to claim: zitadel claim reports it as already owned.

Prove the browser flow

Start the generated app:

npm run dev

Then open the dev server URL, usually http://localhost:3000/login — use exactly the origin setup registered (localhost, not 127.0.0.1): the origin allowlist and passkeys are bound to it, and a passkey registered under one hostname can never assert under another. Complete the browser proof:

register a user -> log out -> log in with the same user -> profile shows signed in

Do not treat a rendered login form as completion. The useful proof is a full register, logout, and login loop in a real browser.

The user you just registered is an end user of your app. The management console is a separate sign-in, as the local admin. The dev server keeps its terminal busy, so open a second terminal in the same directory:

npx @zitadel/cli@alpha console

See Local runtime commands for what that link does and how long it lasts.

Customize the login

Setup scaffolded editable copies of your user schema and login flow into .zitadel/schemas/ and .zitadel/flows/ — each folder has a README explaining what you can change. Edit the files, then preview and publish:

npx @zitadel/cli@alpha plan
npx @zitadel/cli@alpha apply

See Plan and apply for a walkthrough that adds a company field to registration.

Stop or reset

Stop local Zitadel while keeping runtime data:

npx @zitadel/cli@alpha stop

Delete local runtime data:

npx @zitadel/cli@alpha reset --force