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
Your experiences in sequence form, typically imported from
firstflow/experiences.json. Compiled to the internal graph form on receive.
See SCHEMA.md.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.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.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:FirstflowPersistence directly loadInProgress, hasCompleted, recordStart, recordProgress, recordEnd. See useFirstflow.
Identity and resume
The provider readsuser.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 forpage_load, after_idle, custom_event, and url_match. Fire a custom event from anywhere with emit(name) from the hook, or emitCustomEvent(name) standalone.