FabricFabricExperiments
Getting started

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.

The easiest local path is the TypeScript Aspire AppHost:

./aspire.sh restart

This starts:

  • Postgres with the fabric_experiments database on host port 55433,
  • 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 volumes

The 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:16

In 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"
done

If 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_experiments

2. 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 dev

The 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 dev

Open:

http://localhost:3000

4. Sign up, verify email, and create an organization

  1. Open http://localhost:3000/auth/signup.
  2. Create an account.
  3. The local API logs the verification email link to stdout when RESEND_API_KEY is not set.
  4. Open that verification link in your browser.
  5. Sign in at http://localhost:3000/auth/login.
  6. Studio redirects first-time users to /app/new-organization.
  7. 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 / .yml specs,
  • 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.

On this page