docs/.mintlify/skills/framework-integration/references/studio-and-cli.md
The Local Studio is a companion app to @novu/framework. It runs locally, talks to your Bridge Endpoint, and gives you a live preview of every workflow you've registered — including step controls, payload, and rendered output.
npm run dev for Next.js, exposing /api/novu)NOVU_SECRET_KEY exported (from .env)npx novu@latest dev
Defaults:
4000/api/novuhttp://localhost:2022The CLI:
http://localhost:4000/api/novu to discover workflows.https://<id>.novu.sh/api/novu) so Novu Cloud can reach your machine.| Flag | Long form | Default | Purpose |
|---|---|---|---|
-p | --port <port> | 4000 | Your app's port |
-r | --route <path> | /api/novu | Bridge route path |
-o | --origin <url> | http://localhost | Bridge origin |
-d | --dashboard-url <url> | https://dashboard.novu.co | Dashboard URL — use https://eu.dashboard.novu.co for EU |
-sp | --studio-port <port> | 2022 | Studio UI port |
-t | --tunnel <url> | auto | Self-hosted tunnel (e.g. ngrok) |
-H | --headless | false | Skip the Studio UI (just keep the tunnel alive) |
npx novu@latest dev --port 3002
npx novu@latest dev --port 3002 --dashboard-url https://eu.dashboard.novu.co
npx novu@latest dev --route /internal/notify
npx novu@latest dev --tunnel https://my-tunnel.ngrok.app
When using a self-hosted tunnel, the Studio cannot trigger test events because it relies on the auto-generated tunnel for callback. Use the Cloud Dashboard to trigger instead.
Useful in CI or for keeping the tunnel alive without the UI:
npx novu@latest dev --headless
| Created by | URL pattern | Use for | |
|---|---|---|---|
| Tunnel URL | npx novu@latest dev | https://<id>.novu.sh/api/novu | Local dev — Studio + Cloud testing |
| Bridge URL | Your deployed app | https://api.acme.com/api/novu | Production sync |
Tunnel IDs are persisted to your machine, so the same URL is reused across dev runs.
npx novu syncPush workflows defined in code to Novu Cloud.
npx novu@latest sync \
--bridge-url <YOUR_PUBLIC_BRIDGE_URL> \
--secret-key <NOVU_SECRET_KEY> \
--api-url https://api.novu.co
| Flag | Purpose |
|---|---|
--bridge-url | Public URL to your deployed bridge (https://app.com/api/novu) |
--secret-key | NOVU_SECRET_KEY for the target environment |
--api-url | https://api.novu.co (default) or https://eu.api.novu.co for EU |
Each environment (Development, Production) has its own secret key. Sync once per environment with the matching key.
Vercel free-tier previews are protected. Enable Protection Bypass for Automation and append the bypass token:
npx novu@latest sync \
--bridge-url "https://my-app-preview.vercel.app/api/novu?x-vercel-protection-bypass=$BYPASS_TOKEN" \
--secret-key $NOVU_SECRET_KEY
npx novu initBootstrap a complete bridge app with a sample workflow. Designed for first-run users.
npx novu init --secret-key=<YOUR_NOVU_SECRET_KEY>
Created files:
/api/novu route (Next.js).env with NOVU_SECRET_KEYwelcome-email workflow demonstrating Step Controls + React EmailYes — pass -t/--tunnel with your own URL. The preview will work, but you can't trigger test events from the Studio UI.
npx novu@latest dev -t https://my-tunnel.example.com
Common causes:
--port <yourport>--route /custom/pathNODE_ENV isn't development. Either:
NODE_ENV=development for the local bridge process, orstrictAuthentication: false to a custom Client in your serve setupYes — start each bridge on its own port and run a Studio per bridge with --studio-port. Each gets its own tunnel.
NOVU_SECRET_KEY is set in your production env vars/api/novu