A visual node-graph editor and calculator built with React. Create computational flows by wiring nodes together, with 100+ node types, custom node composition, real-time evaluation, and cloud storage.
π New to FlowCal? Start with the User Guide β building your first flow, connecting nodes, groups, custom nodes, sharing, and keyboard shortcuts.
FlowCal's core is free and open source (Apache-2.0) β and there's no lock-in. Run it however you like:
| Self-host (own your data) | Atelier | |
|---|---|---|
| How | docker compose up with any Postgres, or point it at Supabase |
One deploy from this repo β managed database, TLS, public access |
| Support | Community | First-class (one-click deploy, managed flowcal-db, official support) |
Atelier is the paved road, not a requirement: the same open-source FlowCal runs
anywhere. See Hosting below and docs/POSITIONING.md
for how the open project relates to Atelier.
FlowCal runs against either of two interchangeable backends, selected with the
VITE_BACKEND environment variable:
VITE_BACKEND |
Backend | Use when |
|---|---|---|
api (recommended for self-hosting) |
Self-hosted Express + Postgres (server/) |
You want to own your data with docker compose up |
supabase (default) |
Supabase | You already use Supabase |
The frontend talks to whichever backend is active through a single provider
interface (src/services/backend/), so neither backend leaks into the rest of
the app.
Brings up the app (API + SPA in one container) and Postgres:
JWT_SECRET=$(openssl rand -hex 32) docker compose up --buildThen open http://localhost:3001, sign up, and create the first admin:
docker compose exec app npm run create-admin -- you@example.com yourpasswordData persists in the flowcal-db Docker volume. Configurable via env vars
(JWT_SECRET, POSTGRES_PASSWORD, PORT, COOKIE_SECURE β set true behind
HTTPS). See docker-compose.yml.
Atelier can build and host FlowCal straight from this
repo β it clones the repo, builds the root Dockerfile, and runs it. Use the
Clone a Git Repo flow
(guide):
- Deploy Postgres as its own app first (Apps β Create β Deploy an
Image): image
postgres:16, port5432. Set its secretsPOSTGRES_USER/POSTGRES_PASSWORD/POSTGRES_DB, plusPGDATA=/data/pgdataso the database persists on the app's/datavolume. - Clone this repo (Apps β Create β Clone a Git Repo): enter the repo's
HTTPS URL and branch
main. The rootDockerfilebuilds the SPA + API into a single image. (Public repo, or supply a read-only token in the Private repository section.) - Set the app's secrets so it can reach the database and sign sessions:
DATABASE_URL=postgres://<user>:<pass>@<db-app>.atelier-apps.svc.cluster.local:80/<db>(read the DB app's in-cluster URL from its app page; the in-cluster Service forwards port 80 to Postgres)JWT_SECRETβ a long random value (openssl rand -hex 32)ADMIN_EMAIL=you@example.com(optional) β promotes that account to admin on startup once you've signed upCOOKIE_SECURE=falseunless you serve it over HTTPS
The app applies migrations and waits for the database on startup, so it tolerates Postgres still initializing on first deploy.
Accessing the UI β add the DNS entry. FlowCal's SPA uses root-absolute paths, so
the portal proxy (<atelier-domain>/apps/flowcal) won't render it correctly. Open the
app at its dedicated host instead β http://flowcal.<atelier-domain>/ (e.g.
http://flowcal.atelier.home.arpa/), which serves the app at /. That subdomain must
resolve on your machine, so add it to your hosts file (or DNS), pointing at the Atelier
node's IP:
# /etc/hosts (use your node's IP)
192.168.0.22 flowcal.atelier.home.arpa
To expose it on the public internet instead, enable the platform's Public Access (Cloudflare Tunnel) for the app.
npm install
cp .env.example .env # set VITE_BACKEND and the matching backend vars
npm run dev # http://localhost:5173Run the API separately during development (see server/README.md for details):
cd server
cp .env.example .env # set DATABASE_URL, JWT_SECRET
npm install
npm run migrate
npm run dev # http://localhost:3001Point the frontend at it with VITE_API_URL=http://localhost:3001 in the root
.env.
Once you've created your accounts, you'll usually want to stop new ones. How you do that depends on the backend β and the difference matters, because only one of these actually enforces anything.
Self-hosted (VITE_BACKEND=api) β easiest is the Admin panel β Registration:
toggle sign-ups open/closed at runtime. No redeploy, it persists, and it applies to
every instance sharing the database.
To set it at deploy time instead, use the server-side variable:
SIGNUPS_ENABLED=false # in server/.env, then restart the APIPOST /api/auth/signup now returns 403 and the login page hides the sign-up
form. Existing users can still sign in.
Precedence: the env var is the default; an admin's toggle is stored in the database and takes precedence over it. So
SIGNUPS_ENABLEDseeds the initial behaviour rather than acting as a hard lock β anyone you trust with admin can re-open registration from the panel.
On Atelier, set it as a secret (the pods restart automatically):
curl -s -X PUT "$ATELIER_API_URL/api/apps/<app>/secrets" \
-H "Authorization: Bearer $ATELIER_API_TOKEN" -H 'Content-Type: application/json' \
-d '{"secrets":{"SIGNUPS_ENABLED":"false"}}'Supabase (VITE_BACKEND=supabase) β disable "Allow new users to sign up"
in your Supabase project's Authentication β Providers settings. That's the real
enforcement. Optionally also set VITE_SIGNUPS_ENABLED=false to hide the form in
the UI.
β οΈ VITE_SIGNUPS_ENABLEDis a build-time, UI-only flag β it hides the sign-up form but does not close the endpoint. Don't rely on it alone; useSIGNUPS_ENABLED(api) or your Supabase Auth setting (supabase).
Admin panel β Add a user creates an account immediately β and deliberately works even while sign-ups are closed, which is the usual reason you'd want it. The new user can sign in straight away; you're not signed in as them. Only a superuser can create another admin.
(Self-hosted api backend only. On Supabase, add users from the Supabase dashboard β
creating users needs service-role privileges a browser must never hold.)
Set ADMIN_EMAIL on the API server and restart β that already-registered account
is promoted to admin on startup, so you don't need container access.
npm run dev # Vite dev server (HMR)
npm run build # Production SPA build
npm run lint # ESLint
npm run test:run # Vitest (single run)- Graph engine (
src/engine/) βevaluateGraph()performs DFS with cycle detection;nodeDefinitions.jsholds the node-type registry. - Editor (
src/components/Editor.jsx) β canvas state, node CRUD, selection, undo/redo, keyboard shortcuts. - Backend abstraction (
src/services/backend/) β theBackendProviderinterface plus thesupabaseandapiimplementations. - Server (
server/) β the self-hosted Express + Postgres API. Seeserver/README.md.
No TypeScript β JSX only. Styling via Tailwind (six themes in src/themes.js).
- User Guide β how to use FlowCal: your first flow, nodes and wiring, groups and custom nodes, iterators, sharing, and shortcuts.
docs/POSITIONING.mdβ how the open project relates to Atelier.server/README.mdβ the self-hosted API.CONTRIBUTING.mdΒ·SECURITY.md
skills/calc-to-flowcal/ documents the flow JSON format
and node catalog so an LLM can turn a calculation (e.g. (base + tax) * qty) into an
importable FlowCal flow. It includes the schema, the evaluation model, the full node
reference, and verified examples.
Contributions are welcome β see CONTRIBUTING.md. We use a
Developer Certificate of Origin (DCO): sign off your commits with git commit -s.
To report a security issue, see SECURITY.md.
If FlowCal is useful to you, please give it a star. It's a small thing, but it's genuinely the clearest signal that this is worth continuing β and it keeps me building. Thank you.
Not a coder? Sharing a flow you've built, filing an issue, or telling someone who'd find it useful all help just as much.
You can also follow @tryatelierai on X for updates on FlowCal and what's next.
Licensed under the Apache License 2.0 Β© Edward Howard.
The FlowCal open core is fully open source. Hosting (via the
Atelier platform) and premium team/scale features β
real-time collaboration, deep version history, team workspaces, enterprise SSO β
are part of the separate commercial edition. See
docs/POSITIONING.md.
