Start the web UI locally
Run the Fabric Experiments API and Studio UI on your machine.
The web UI is called Studio. It is the hosted control-plane UI for organization onboarding, no-code experiment authoring, YAML import, API key management, audit history, and governed lifecycle actions.
Studio talks to apps/api; it does not read or write Postgres directly. Server components and server actions forward the user cookie to the API so auth, org membership, and role checks stay centralized.
When should I use Studio?
Use Studio when you are testing the hosted API path:
Use local fx commands when you are testing file-backed experiments in .fx/:
To move local YAML into the hosted control plane, use either Studio Import YAML or fx push.
Recommended: start everything with Aspire
The easiest local path is the TypeScript Aspire AppHost:
./aspire.sh restartThis starts:
- Postgres with the
fabric_experimentsdatabase on host port55433, - a migration step for
infra/neon/migrations/*.sql, - the hosted API at
http://localhost:4100, - Studio at
http://localhost:3100, - the Aspire dashboard at
https://localhost:17135.
These Aspire ports intentionally differ from ~/Development/fabric-autorefi so both projects can run side by side.
Useful commands:
./aspire.sh status
./aspire.sh down
./aspire.sh dashboard
./aspire.sh clean # destructive: removes containers and volumesThe manual setup below is still useful when you want to run services individually.
1. Start Postgres manually
Use any local Postgres. For a quick Docker database:
docker run --rm --name fx-postgres \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=fabric_experiments \
-p 5432:5432 postgres:16In another terminal, apply migrations:
export DATABASE_URL=postgres://postgres:postgres@localhost:5432/fabric_experiments
for f in infra/neon/migrations/*.sql; do
psql "$DATABASE_URL" -f "$f"
doneIf port 5432 is already in use, map another host port, for example -p 55432:5432, and set:
export DATABASE_URL=postgres://postgres:postgres@localhost:55432/fabric_experiments2. Start the API
From the repository root:
export DATABASE_URL=postgres://postgres:postgres@localhost:5432/fabric_experiments
export BETTER_AUTH_SECRET=$(node -e "console.log(crypto.randomBytes(32).toString('hex'))")
export MANIFEST_KEY_ENC_KEY_HEX=$(node -e "console.log(crypto.randomBytes(32).toString('hex'))")
export WORKER_API_TOKEN=$(node -e "console.log(crypto.randomBytes(32).toString('hex'))")
export FX_BASE_URL=http://localhost:4000
export FX_TRUSTED_ORIGINS=http://localhost:3000
pnpm --filter @fabricorg/experiments-api devThe API runs at http://localhost:4000.
3. Start Studio
From another terminal at the repository root:
export FX_API_BASE_URL=http://localhost:4000
export NEXT_PUBLIC_FX_API_BASE_URL=http://localhost:4000
pnpm --filter @fabricorg/experiments-studio devOpen:
http://localhost:30004. Sign up, verify email, and create an organization
- Open
http://localhost:3000/auth/signup. - Create an account.
- The local API logs the verification email link to stdout when
RESEND_API_KEYis not set. - Open that verification link in your browser.
- Sign in at
http://localhost:3000/auth/login. - Studio redirects first-time users to
/app/new-organization. - Create an organization, then Studio redirects to
/app/{orgSlug}/experiments.
Studio routes are URL-scoped by organization. Switching organizations sends you to /app/{orgSlug} and invalidates the old context instead of relying on an implicit active org fallback.
5. Create or import experiments
From the organization dashboard you can:
- click Create experiment for the no-code authoring form,
- click Import YAML to upload one or more local
.yaml/.ymlspecs, - open an experiment detail page to edit, submit for review, approve, start, pause, resume, conclude, or kill.
Studio validates imported YAML with the same shared parser used by the CLI package.
6. Create an API key for hosted CLI workflows
Open /app/{orgSlug}/settings, create an API key, and copy it immediately. The plaintext key is shown once.
Then push local YAML to the hosted API:
fx push experiments/ \
--api-url http://localhost:4100 \
--api-key fx_key_... \
--tenant <organization-id>You can also use environment variables:
export FX_API_URL=http://localhost:4100
export FX_API_KEY=fx_key_...
export FX_ORG_ID=<organization-id>
fx push experiments/Studio surfaces
- sign up and sign in,
- first-run organization onboarding,
- organization switcher,
- URL-scoped org routes,
- install snippet generator for drop-in web delivery,
- experiment list and detail,
- no-code experiment create/edit with Mojito-parity fields,
- trigger, holdback, divert, manual-exposure, DOM ops, JS/CSS, metadata, and payload authoring,
- YAML import,
- signed preview-link generation,
- lifecycle actions,
- audit log,
- org API key creation/copy/revoke,
- SAML settings route for org owners.
Studio is designed as the primary customer UI for onboarding, installing the tag-loader, creating/importing experiments, previewing variants, promoting lifecycle states, and managing API keys.