> ## Documentation Index
> Fetch the complete documentation index at: https://docs.firstflow.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Self-hosting overview

> FirstFlow is an open-source SDK that runs entirely on your own infrastructure: your app, your Supabase project, and your experiences in git. There is no FirstFlow server to operate.

FirstFlow is open-source under the MIT license. It is not a platform you deploy and operate it is a set of **SDK packages you embed in your own product**. There is no FirstFlow backend, no dashboard, and no service to keep running. Authored content lives in your git repo; runtime data lives in a Supabase project you own.

This page explains what actually runs when you use FirstFlow: the three packages, where each piece of state lives, and what "self-hosting" means for a client-evaluated SDK. Read it before the [Quickstart](/self-hosting/quickstart) so the steps there have a model to hang on.

<Note>
  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.
</Note>

## 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.

```mermaid theme={null}
flowchart LR
  subgraph repo["Your git repo"]
    EXP["firstflow/experiences.json"]
  end

  subgraph app["Your application"]
    FE["Your frontend (React)<br/>@firstflow/runtime<br/>FirstflowProvider + FirstflowWidget"]
    BE["Your backend (Node)<br/>@firstflow/runtime-server<br/>ff.wrap(llm) · classifyIntent"]
  end

  subgraph sb["Your Supabase project"]
    DB[("Postgres<br/>firstflow_flow_runs<br/>firstflow_llm_calls<br/>firstflow_conversations<br/>firstflow_traces")]
  end

  EXP -->|"import at build"| FE
  FE -->|"@supabase/supabase-js (anon key)"| DB
  BE -->|"@supabase/supabase-js (service role key)"| DB

  style FE fill:#7C3AED,stroke:#5B21B6,color:#fff
  style BE fill:#16A34A,stroke:#15803D,color:#fff
  style DB fill:#0D9488,stroke:#0F766E,color:#fff
  style EXP fill:#1F2937,stroke:#111827,color:#fff
```

There is no socket and no server-side eligibility engine. Triggers, frequency caps, audience conditions, and branching are all evaluated **client-side** by `@firstflow/runtime` from the experiences you ship. The Supabase calls persist and resume progress; they do not decide what to show.

## The three packages

| Package                                         | Runs in           | What it does                                                                                     |
| ----------------------------------------------- | ----------------- | ------------------------------------------------------------------------------------------------ |
| [`@firstflow/runtime`](/react/overview)         | Browser           | React widget renders flows, evaluates triggers and audience, persists progress                   |
| [`@firstflow/runtime-server`](/server/overview) | Your Node backend | Wraps your LLM client for cost/token/latency observability; intent classification; token signing |
| `@firstflow/config-schema`                      | Both              | Shared types, Zod validators, and the Supabase migrations                                        |

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_runs` in 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](/self-hosting/auth-and-orgs).

## What self-hosting requires

Three things, and the first is the only hard requirement:

1. **A Supabase project** with the FirstFlow migrations applied. See [Set up Supabase](/self-hosting/supabase-cloud).
2. **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](/self-hosting/quickstart).
3. **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](/self-hosting/oauth-providers), backups), keeping the Supabase **service-role key** server-only, and applying migrations as they ship. The full division of labor is in [Responsibilities](/self-hosting/responsibilities), and the hardening list is in [Production](/self-hosting/production).

## Next

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/self-hosting/quickstart">
    Install, point at Supabase, and render your first experience.
  </Card>

  <Card title="Set up Supabase" icon="database" href="/self-hosting/supabase-cloud">
    Create the project and apply the migrations.
  </Card>

  <Card title="Configuration" icon="sliders" href="/self-hosting/configuration">
    The environment variables FirstFlow actually reads.
  </Card>

  <Card title="Production" icon="shield-check" href="/self-hosting/production">
    RLS, key hygiene, and backups before you go live.
  </Card>
</CardGroup>
