The whole product is these packages plus your Supabase project. “Self-hosting”
here just means the data and the rendering both stay on infrastructure you
control there is no separate service to run.
The model
FirstFlow has three parts, and you own all three:- Authored content your experiences (onboarding, tours, surveys, announcements) as
experiences.json(or.ts) committed to your git repo. Changing an experience is a normal code change and deploy. - The runtime
@firstflow/runtime, a React widget that loads those experiences, evaluates triggers and audience rules in the browser, renders the active step, and persists progress. - Your data a Supabase (Postgres) project you create. Flow runs, LLM calls, conversations, and traces are written to
firstflow_*tables there. FirstFlow never sees your data.
@firstflow/runtime from the experiences you ship. The Supabase calls persist and resume progress; they do not decide what to show.
The three packages
The frontend package is the only one you strictly need. The server package is optional add it when you want LLM observability or intent classification.
config-schema ships the SQL migrations you apply to your Supabase project.
Where state lives
Nothing is hidden in a FirstFlow-operated service, because there isn’t one.- Experiences your git repo, imported into the app at build time.
- Progress and resume
firstflow_flow_runsin your Supabase, via the persistence adapter you pass to the provider. - LLM observability
firstflow_llm_calls,firstflow_conversations,firstflow_conversation_messages,firstflow_traces, written by@firstflow/runtime-server. - End-user identity whatever your app passes as
user.id. FirstFlow trusts it; your own auth decides who the user is. Unidentified visitors get a stable anonymous id.
What self-hosting requires
Three things, and the first is the only hard requirement:- A Supabase project with the FirstFlow migrations applied. See Set up Supabase.
- A clone of the repo with your app built inside its workspace (the packages aren’t on npm you reference them with
workspace:*). See Quickstart. - An LLM client of your own (Anthropic, OpenAI, or any OpenAI-compatible endpoint) only if you use the intent classifier or wrap an LLM. You build the client and give it a key from any source; FirstFlow just wraps it and reads no key itself. Everything else runs without one.
What you are responsible for
Self-hosting an SDK is light on operations, because you are not running a FirstFlow server you are running your app against your Supabase. Your duties are the database (provisioning, Row Level Security, backups), keeping the Supabase service-role key server-only, and applying migrations as they ship. The full division of labor is in Responsibilities, and the hardening list is in Production.Next
Quickstart
Install, point at Supabase, and render your first experience.
Set up Supabase
Create the project and apply the migrations.
Configuration
The environment variables FirstFlow actually reads.
Production
RLS, key hygiene, and backups before you go live.