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.
Core concepts
| Term | Definition |
|---|
| Agent | A workspace that groups your experiences, audience, and settings. One agent per AI product or environment. |
| Experience | A single flow — a tour, survey, or announcement — with its content, triggers, and audience settings. |
| Flow | The node graph that defines an experience: the sequence of messages, decisions, and actions. |
| Node | A single step in a flow. Types: message, decision, announcement. |
| Edge | A directed connection between two nodes. Decision nodes have multiple outgoing edges, one per branch. |
| Trigger | The condition that causes an experience to appear: chat_opens, after_user_message, after_idle, or custom_event. |
| Audience | Who sees an experience: everyone, a named segment, or users matching trait rules. |
| Segment | A server-computed group of users (e.g., “Pro plan users”). Membership is calculated by the backend and returned in the SDK config. |
Architecture
┌─────────────────────────────────────────────────────────┐
│ Dashboard (Next.js) │
│ Create experiences, set triggers, manage audience │
└─────────────────────┬───────────────────────────────────┘
│ REST API
┌─────────────────────▼───────────────────────────────────┐
│ API (NestJS + PostgreSQL) │
│ Stores experiences (flow graph + settings) │
│ Computes audience segment memberships │
│ Webhooks via Svix │
└─────────────────────┬───────────────────────────────────┘
│ GET /agents/:id/config
┌─────────────────────▼───────────────────────────────────┐
│ SDK (@firstflow/react / nextjs / react-native) │
│ Fetches config → evaluates eligibility │
│ FirstflowWidget renders the active experience │
└─────────────────────────────────────────────────────────┘
The API stores two representations of each experience:
flow — the full editor graph (used by the Dashboard builder)
flowRuntime — a stripped version with editor-only nodes removed (used by the SDK)
Experience lifecycle
1. Design-time (Dashboard)
You build an experience using the visual flow editor:
- Add message or decision nodes
- Connect them with edges
- Configure triggers (when it shows) and audience (who sees it)
- Set frequency, device, and schedule
- Publish (status →
active)
2. Fetch
The SDK fetches GET /agents/:id/config on mount. The response includes all active experiences for the agent, including flow graphs, settings, and the current user’s segment memberships.
Config is cached in memory for 5 minutes. Subsequent mounts with the same agentId + apiKey reuse the cache.
3. Eligibility evaluation
For each experience, the SDK runs this check client-side:
status === "active"
AND device matches (desktop / mobile / all)
AND schedule window is open (start ≤ now < expiry)
AND frequency limit not reached (checked against localStorage)
AND audience matches (all, or segment membership, or trait rules)
AND trigger condition is satisfied
The highest-priority passing experience is shown first.
4. Rendering
FirstflowWidget renders the active experience. Placement is either:
overlay — centered modal over the chat
inlineStack — inline, above the chat input
5. Node execution
The SDK walks the flow graph:
- Start at the first non-editor node
- Render the node (message, announcement, decision)
- On user action (CTA click, survey answer, dismiss), follow the outgoing edge
- For decision nodes, evaluate branch conditions to pick the next node
- Continue until there are no more outgoing edges
6. Analytics
The SDK fires events throughout the flow. Events are batched and sent to the analytics pipeline:
| Event | When |
|---|
experience.started | First node rendered |
experience.completed | No more nodes remain |
experience.dismissed | User dismisses |
survey.answer | User answers a question |
survey.submitted | Survey flow completes |
announcement.clicked | CTA activated |
Decision nodes
A decision node splits the flow into up to 3 branches. Each branch has conditions (AND within a branch, OR across branches). The first branch whose conditions match determines the next node.
Decision node
├── Branch "If" (conditions: plan equals "pro") → Node A
├── Branch "Else if" (conditions: plan equals "free") → Node B
└── Branch "Else" (no conditions → always matches) → Node C
Branch conditions can evaluate:
- User traits:
traits.plan, traits.role, etc.
- Survey answers:
answers.<questionId>
Frequency tracking
The SDK tracks how many times each experience has been shown, stored in localStorage (or sessionStorage for session-scoped limits).
| Frequency type | Behavior |
|---|
once | Show one time, ever |
limited | Show up to N times per session, day, week, or lifetime |
always | No limit |
Storage keys use the prefix ff_exp_ — clear them to reset frequency for testing.