Skip to main content
This is the whole setup: install the packages, apply the migrations to a Supabase project you own, author one experience in your repo, mount the provider, and (optionally) wrap your LLM client. The runtime evaluates everything in the browser, so there is no FirstFlow service to run.

Prerequisites

  • Node 18+ and pnpm 9 (the repo’s package manager).
  • git to clone the repo.
  • A Supabase project free tier is fine. Create one at supabase.com/dashboard.
You consume FirstFlow by cloning the repo and building your app inside its workspace. The packages aren’t published to npm; your app references them locally with workspace:*.

Steps

1

Fork, clone, and build

Fork firstflow-oss (so you can commit your own app into it), clone your fork, install, and build the packages once.
2

Add your app to the workspace

Scaffold your app in a new folder inside the repo with your stack’s usual tool:
Add its folder to the workspace and reference the packages with workspace:*:
pnpm-workspace.yaml
apps/web/package.json
Then run pnpm install from the repo root. Only @firstflow/runtime + @supabase/supabase-js are required; add @firstflow/runtime-server for LLM observability.
workspace:* only resolves inside this monorepo that’s why your app lives here. Re-run pnpm build after editing any package so your app picks up the change.
3

Set up Supabase

Create a project, then paste packages/config-schema/supabase/schema.sql into the Supabase SQL editor and run it once one file creates the whole schema. Full walkthrough in Set up Supabase.Then put the keys in your environment. Three values: the project URL and anon key are public (browser-safe); the service_role key is server-only. The variable names depend on your bundler public values must carry its client-env prefix:
.env.local
The NEXT_PUBLIC_ / VITE_ / REACT_APP_ prefix is just how each bundler exposes a value to the browser. The runtime itself takes plain strings see Configuration.
4

Author your first experience

Create firstflow/experiences.json in your repo. This file is your source of truth it is versioned in git and imported at build time.
firstflow/experiences.json
The full step and action reference is in config-schema/SCHEMA.md.
5

Mount the provider and widget

@firstflow/runtime is plain React it works in any stack. Wrap your app once; only how you read the env differs. The default Supabase persistence adapter ships with @firstflow/runtime/supabase.
app/firstflow.tsx
Mount <Firstflow> in your root layout. The provider is a client component (it uses hooks + localStorage). See Next.js.
Pass user={{ id, traits }} from your own auth for signed-in users. It’s optional omit it and the runtime uses a stable per-browser anonymous id so caps and resume still work.
6

(Optional) Observe your LLM calls

@firstflow/runtime-server is framework-agnostic Node set it up once with your server-only service-role key, then wrap your LLM client wherever you call it. The setup is identical across backends:
firstflow.server.ts
Then call it from your handler:
app/api/chat/route.ts
Each call records a row in firstflow_llm_calls. See the Server SDK for traces, intent classification, and bring-your-own OpenAI-compatible clients.
7

Run it

Start your app. The welcome experience auto-fires after one second.
Run through it, then check Supabase firstflow_flow_runs has a completed row.

Verify

A working setup shows three things:
  1. The widget appears in the corner and advances through your experience.
  2. firstflow_flow_runs gains a row per run (in-progress, then completed/dismissed).
  3. If you wrapped an LLM client, firstflow_llm_calls gains a row per call.
If the widget never appears, confirm the experience status is "active" and the Supabase keys are set. If progress never persists, check the migrations are applied and Row Level Security allows the write.

Next

Set up Supabase

Create the project and apply the migrations in order.

Configuration

Every environment variable FirstFlow reads.

Identity & auth

How user.id and anonymous visitors work.

Production

RLS, key hygiene, and backups.