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.
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 Then run
- Next.js
- Vite + React
workspace:*:pnpm-workspace.yaml
apps/web/package.json
pnpm install from the repo root. Only @firstflow/runtime +
@supabase/supabase-js are required; add @firstflow/runtime-server for LLM
observability.3
Set up Supabase
Create a project, then paste
The
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:- Next.js
- Vite + React
- Create React App
.env.local
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 The full step and action reference is in
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
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.- Next.js (App Router)
- Vite + React
app/firstflow.tsx
<Firstflow> in your root layout. The provider is a client
component (it uses hooks + localStorage). See Next.js.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
- Next.js route handler
- Express
- Hono
app/api/chat/route.ts
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:- The widget appears in the corner and advances through your experience.
firstflow_flow_runsgains a row per run (in-progress, then completed/dismissed).- If you wrapped an LLM client,
firstflow_llm_callsgains a row per call.
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.