Skip to main content
FirstflowProvider is the root of the browser SDK. It compiles the experiences you pass, runs the trigger engine, tracks the active run, and exposes everything through useFirstflow. Mount it once, high in your tree.

Props

experiences
Experience[]
required
Your experiences in sequence form, typically imported from firstflow/experiences.json. Compiled to the internal graph form on receive. See SCHEMA.md.
user
FirstflowUser
The end user: { id, email?, createdAt?, traits? }. Optional omit it and the runtime falls back to a stable per-browser anonymous id. traits drive audience targeting and branching.
persistence
FirstflowPersistence
Where in-progress runs are stored and resumed. Pass createSupabasePersistence(supabase) from @firstflow/runtime/supabase, or implement the interface for another backend. Without it, the widget still renders but nothing persists or resumes.
onEvent
(event: FirstflowEvent) => void
Called for every runtime event experience.shown, step.entered, answer.submitted, action.triggered, experience.completed, experience.dismissed. Route them to your own analytics.

Persistence

The default Supabase adapter is the fast path:
For another backend (your API, Mongo, Firestore), implement FirstflowPersistence directly loadInProgress, hasCompleted, recordStart, recordProgress, recordEnd. See useFirstflow.

Identity and resume

The provider reads user.id as the subject of once_per_user caps and in-progress resume. When user is absent it uses getAnonymousId(), so anonymous visitors still get caps and resume; their traits.anonymous is true. Pass a real id once the user signs in. See Identity.

Triggers

On mount the provider resumes any in-progress run (one read), then starts the trigger engine for page_load, after_idle, custom_event, and url_match. Fire a custom event from anywhere with emit(name) from the hook, or emitCustomEvent(name) standalone.

Next

Render with FirstflowWidget, drive it with useFirstflow, or build a custom shell.