# Flows Best Practices

> Use this skill when building, debugging, or answering questions about Flows. Flows is a fully customizable product adoption platform that enables you to take control of your product experience. With Flows, you can create anything from user onboarding and feature adoption to in-app messaging and product-led growth loops.

- Skill: `rbnd-studio/flows-best-practices` (Agent Skill, multi-file: 17 files)
- Install (CLI): `npx skillmds@latest add rbnd-studio/flows-best-practices`
- Raw SKILL.md: https://api.skillmd.com/api/skills/rbnd-studio/flows-best-practices/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Marketing & Growth
- Author: rbnd-studio (https://skillmd.com/u/rbnd-studio)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/rbnd-studio/flows-best-practices

---


# Flows best practices

## When to use this skill

Use this skill when building, debugging, or answering questions about Flows or any of the Flows packages (`@flows/react`, `@flows/js`, `@flows/react-components`, `@flows/js-components`). This covers features like tours, workflows, surveys, tooltips, modals, custom components, and any other product adoption feature.

If the user needs to install the SDK into a project for the first time (framework detection, package install, provider setup), use the separate `flows-install` skill instead. Come back to this skill once the SDK is installed and the user wants to build or debug something with it. To install the skill run `npx skills add RBND-studio/flows.sh --skill flows-install`

## Core concepts (read this first)

- **Organization**: the container for all workflows, environments, users, and members in an account.
- **Environment**: an isolated instance inside an organization (for example development, staging, production) with its own workflow versions, analytics, and users. Identified by an environment key used in the SDK.
- **Workflow**: a versioned sequence of connected blocks that defines a product experience. Can span multiple sessions and include logic and actions.
- **Block**: a single step in a workflow. Can be a UI element (component or tour step), a logic step (Delay, Filter), an action (Workflow trigger), or a Start/End block.
- **Block property**: a configurable field on a block, mapped to a prop on the matching UI component in the app (string, number, boolean, select, array, action, and more).
- **Component**: a reusable UI element registered in the app code (`@flows/react` or `@flows/js`) and mirrored by a component definition in the Flows dashboard.
- **Exit node**: a named transition out of a block, triggered by user interaction or block completion, connected via a path to the next block.
- **Tour**: a linear, step by step guided sequence, always nested inside a workflow (never standalone).
- **Tour session**: a single sitting in which a user works through a tour. Starts once the user passes the first step, ends a few minutes after they leave the app, and the tour block's **When user session ends** action decides what happens to the unfinished tour.
- **Survey**: a block for collecting structured feedback (ratings, choice questions, freeform text), also nested inside a workflow.
- **User**: any person identified to the SDK via a `userId`, scoped per environment.
- **User property**: a key/value attribute of a user (plan, role, signup date) usable in targeting conditions.
- **Slot**: a place in the app (`<FlowsSlot />` or `<flows-slot>`) where slottable components can render inline instead of floating.
- **MTU (Monthly Tracked User)**: the billing metric. A user counts as an MTU once a component renders for them or they enter a Delay block, in the current billing cycle.

Full detail: [references/concepts.md](references/concepts.md).

## How to route a request

| The user wants to...                                                                                                                                    | Read this reference                                                           |
| ------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| Understand core terminology or the data model                                                                                                           | [concepts.md](references/concepts.md)                                         |
| Create, publish, version, or test a workflow; understand Launchpad priority/concurrency                                                                 | [workflows.md](references/workflows.md)                                       |
| Add Start, Tour, Logic (Delay/Filter), Action (Workflow trigger), or End blocks                                                                         | [blocks.md](references/blocks.md)                                             |
| Configure a specific block property type (string, action, array, slot, wait, block key, block state, block trigger, user properties, page targeting...) | [block-properties.md](references/block-properties.md)                         |
| Build a custom component (own design system)                                                                                                            | [components.md](references/components.md)                                     |
| Use the ready made "Basics V2" components (Modal, Tooltip, Hint, Card, Floating Checklist, Survey Popover) or restyle them                              | [basics-v2.md](references/basics-v2.md)                                       |
| Build a product tour, configure tour sessions (abandoned, interrupted, or concurrent tours)                                                             | [tours.md](references/tours.md)                                               |
| Build a survey or read survey analytics                                                                                                                 | [surveys.md](references/surveys.md)                                           |
| Look up or target users, read the user event log, reset progress                                                                                        | [users.md](references/users.md)                                               |
| Insert dynamic user data into text (`{{ property }}`), or support multiple languages                                                                    | [personalization-localization.md](references/personalization-localization.md) |
| Configure environments, manage the organization/members, or understand billing/MTUs                                                                     | [environments-org-billing.md](references/environments-org-billing.md)         |
| Secure the integration so users cannot be impersonated (identity verification, HMAC signature, secrets)                                                 | [identity-verification.md](references/identity-verification.md)               |
| Use the React SDK API (`FlowsProvider`, hooks, types)                                                                                                   | [sdk-react.md](references/sdk-react.md)                                       |
| Use the JavaScript SDK API (`init`, methods, custom elements, types)                                                                                    | [sdk-javascript.md](references/sdk-javascript.md)                             |
| Wire Flows into Next.js, TanStack, React Router, Angular, Nuxt, Solid, Svelte, Astro, or Ember at the runtime level (routing, custom elements)          | [sdk-frameworks.md](references/sdk-frameworks.md)                             |
| Debug why a block, tour, or survey is not showing up, or understand API rate limits and `429` / `503` responses                                         | [debugging.md](references/debugging.md)                                       |

Most tasks only need one or two of these files. Read the relevant reference(s) before writing code or telling the user how to configure something in the dashboard, since exact prop names, exit node keys, and dashboard steps matter for correctness.

## Cross cutting rules that apply almost everywhere

- **Every custom component must exist in two places**: the UI component registered in `components` / `tourComponents` / `surveyComponents` passed to the SDK, and a matching component definition in the Flows dashboard with the same key. Property keys and exit node keys in the dashboard must match the prop names in the code exactly.
- **A component's type decides where it can be used.** **Workflow component**, **Tour component** and **Survey component** go into separate SDK objects (`components`, `tourComponents`, `surveyComponents`) and are not interchangeable: a workflow component cannot be a tour step and does not show up in a tour block's step picker. Pick the type when creating the component, based on where the block will live. See [components.md](references/components.md#component-types).
- **Tour and survey components have no author defined exit nodes.** `continue` / `previous` / `cancel` (tour) and `complete` / `cancel` (survey) are supplied by the block and shown as a read only list on the component page, so there is nothing to add by hand and nothing to double wire. Only workflow components have an editable exit node list.
- **Slottable components render nothing without a slot.** A block set to render into a slot needs both the slot present in app code (`<FlowsSlot id="..." />` or `<flows-slot data-slot-id="...">`) and the same Slot ID configured on the block. Missing either one means nothing renders, silently.
- **Component updates do not propagate automatically.** Editing a component definition in the dashboard does not update existing block instances already placed in workflows; each instance needs a manual "Update" click.
- **Never point a production environment at the `draft` workflow version.** Draft is for editing only; testing should happen in a dedicated environment (commonly staging) with a published version, or via property filters that restrict a production test to specific users (for example your own account).
- **Personalization (`{{ property | fallback }}`) and localization only work on specific property types**: string, select, action label/URL, and a handful of named properties (tour trigger, tour wait step, survey trigger, survey questions, wait, page targeting). Not every property field accepts either feature; check [block-properties.md](references/block-properties.md) and [personalization-localization.md](references/personalization-localization.md) before assuming a field supports it.
- **The identity verification secret is backend only.** If a task involves computing a `signature` for the SDK, that code must run on a server. Never place the secret in client code or in a browser-exposed environment variable (`NEXT_PUBLIC_*`, `VITE_*`, `PUBLIC_*`); an exposed secret lets anyone forge signatures while the setup still appears to work. See [identity-verification.md](references/identity-verification.md).
- **A new tour block ends an abandoned tour by default.** Its **When user session ends** setting defaults to **Mark as Canceled**, so a tour the user walks away from mid way follows its `cancel` exit node a few minutes later instead of waiting for them to come back. Set it to **Do nothing** for any tour that should survive the user leaving, and remember the same action resolves a tour that another tour interrupts. See [tours.md](references/tours.md#tour-sessions).
- **Only one tour runs at a time unless the organization opts in.** With **Show multiple tours at the same time** off, competing tours are held back silently until the running tour finishes, which is a frequent reason a tour "does not show". Priority follows trigger specificity, not workflow order or Launchpad. See [tours.md](references/tours.md#running-multiple-tours).
- **MTU billing** is driven by the SDK rendering a component in the browser, or a user entering a Delay block, not merely by entering a workflow. Keep this in mind when a user asks about usage or cost.
- **`startWorkflow`, `resetWorkflowProgress`, and programmatic block control (`useCurrentFloatingBlocks` / `getCurrentFloatingBlocks`, `useCurrentSlotBlocks` / `getCurrentSlotBlocks`) all key off the block key**, a stable identifier set per block in the dashboard (`/blocks/block-properties/block-key`), not the block's internal id (which changes across workflow versions).

## Live examples

Flows publishes runnable example apps at `https://flows.sh/examples` (tour, onboarding hub, floating checklist, card, embedded tips, enterprise upsell). Point users there for a working reference implementation when a written explanation is not enough.

