Visual node canvas for chaining LLM, image, and video models via OpenRouter. Wire nodes, run pipelines—no glue code.
GitHub
·
OpenRouter
·
| Canvas | Drag nodes from a palette, connect outputs to inputs, run one node or Run all in dependency order. |
| Models | Anything OpenRouter exposes—chat, vision-capable models, image generators, video jobs (including alpha APIs where applicable). |
| Your key | Bring your own OpenRouter API key; usage is billed by OpenRouter. The app proxies requests through your server so the key is not sent straight from the browser to openrouter.ai. |
| Accounts | Sign up to sync encrypted API key (with AUTH_SECRET), canvas, saved workflows, theme, and video job metadata in SQLite—resume on another device. |
| Self-host | Run locally or in Docker; export/import workflows as JSON for backups. |
npm install
cp .env.example .env
# Set AUTH_SECRET (e.g. openssl rand -base64 32) and NEXTAUTH_URL in .env
npx prisma migrate dev # creates SQLite DB for auth
npm run devWith the example .env, the dev server uses port 3080 (see PORT and NEXTAUTH_URL). Open http://localhost:3080, register or sign in, then paste your OpenRouter API key in the studio when prompted (keys are not required in .env for local dev).
npm run build
npm startSet NEXTAUTH_URL and AUTH_SECRET to match your public URL and a long random secret. AUTH_SECRET also encrypts stored OpenRouter keys in the database.
Images use Next.js standalone. Each container start runs prisma migrate deploy (docker-entrypoint.sh) so the schema exists before node server.js. The process runs as nextjs with a writable /app for SQLite.
1. Environment
cp .env.example .envMinimum in .env: AUTH_SECRET, NEXTAUTH_URL (no trailing slash). DATABASE_URL defaults to file:./dev.db inside the container.
2. Build and run
docker compose up --build -dDifferent host port? Set APP_PORT (and matching NEXTAUTH_URL) in .env, for example:
APP_PORT=3000 NEXTAUTH_URL=http://localhost:3000 docker compose up --build -dOr edit .env before docker compose up. NextAuth must use the same origin you open in the browser.
Compose may load .env; it sets AUTH_TRUST_HOST=true for port mapping and reverse proxies. Persist SQLite with a volume on /app/dev.db (or similar) if you need data to survive container removal.
nginx on the same host: The app listens on 127.0.0.1:${APP_PORT:-3080} on the host (mapped to port 3000 inside the container). Point your server / location at that upstream, for example proxy_pass http://127.0.0.1:3080;. Set NEXTAUTH_URL to your public https://your.domain (no trailing slash). The hostname in container logs (e.g. f5030adb7722) is only valid inside Docker—not the URL you use in nginx or a browser.
| Area | Choice |
|---|---|
| Framework | Next.js 16 (App Router) |
| UI | React 19, Tailwind CSS v4, Base UI / shadcn-style components |
| Canvas | @xyflow/react (React Flow v12) |
| State | Zustand (graph + UI; theme + sync via /api/settings/studio when signed in) |
| Auth | NextAuth.js v5, @auth/prisma-adapter |
| Database | Prisma 7, SQLite, better-sqlite3 adapter |
| Language | TypeScript |
- After sign-in, the studio loads your saved state from the server; edits debounce and sync automatically.
- Add Prompt, LLM, Image, Video, input nodes, Notes, and Output; connect compatible handles.
- Choose models and parameters per node; run steps individually or use Run all where supported.
- Server route handlers call OpenRouter with your key; video flows use polling and proxied downloads.
For payload details and model notes, see openrouter-studio-prompt.md and app/api/openrouter/.
Licensed under the Apache License 2.0. See LICENSE.