Getting started / How it works
How it works
The backend is the brain and the client is a renderer. That single decision is what lets flows be authored, experimented on and rewritten without your app knowing any of it happened.
1. A profile of your app
Everything starts from what the system knows about your app: what it does, who it is for, its aha moment, the words it is allowed to use, and the colours and type it should draw in. That profile is assembled from your store listing, screenshots you upload, behaviour once events start arriving, and your answers to five questions.
Every fact records where it came from, and the ordering is enforced: a measurement beats something you stated, and something you stated beats something the system guessed. An unconfirmed inference can never overwrite a fact.
2. A plan, then an authoring loop
The planner decides which activation flows your app is missing, choosing from a fixed set of archetypes with a stated reason for each pick and each hold. The author then turns that plan into real screens: generate, apply your theme, render, repair, repeat within a bounded number of rounds.
3. Deploy validates, versions, and stores
Publishing validates the flow, bumps its version and stores it. Anything a flow can draw is already compiled into the SDK in your app; what gets published is the arrangement — which pieces, in what order, with what copy and what design. That is why a new screen ships without an SDK update and without a store review.
4. The server decides what to show
Your app registers a presenter and never names a flow. When it comes to the foreground, when you track a relevant event, or when a flow finishes, the SDK asks the server whether anything should be shown; the server evaluates triggers and answers with a flow key, or with nothing. Your app can always decline.
Flows are expanded at serve time. Experiment assignment, personalization and variable substitution all happen on the server, so the client never knows a variant exists — which is what keeps experiments honest and lets an old binary render a flow written this morning.
5. Rendering is fully native
The SDK builds real platform UI — SwiftUI views, whether your app is native or Flutter, because the Flutter package hosts the same Swift engine rather than reimplementing it. There is no WebView anywhere, so scrolling, animation, haptics and fonts feel like the rest of your app. Screens that need OS capabilities — sign-in, permissions, purchases — hand off to handlers you register, so your existing auth and billing code stays in charge.
The contract is deliberately forgiving: an older SDK that meets something it does not recognise draws a neutral placeholder instead of crashing, and a flow it cannot read at all falls back to the cached copy. On the device the SDK is cache-first — a previously fetched flow renders instantly while a background request revalidates it for next time. More on caching →
6. Events close the loop
As users move through a flow the SDK reports lifecycle events — flow started, screen changed, answers set, purchase stages, completed or abandoned — batched, deduplicated and durable across offline periods. Those events feed funnel analytics, and with a RevenueCat or Adapty connection the funnel extends past install to trials, payments and refunds.
They also feed the optimizer, which is where the loop actually closes: detect a drop-off, form a hypothesis, validate it against your policy, run the experiment, promote what wins, and write what it learned to the pattern library. See Optimizer & growth memo.
What this architecture buys
- Machine-written screens can be checked. One solver means a generated flow is renderable and inspectable before a user sees it, which is the difference between autopilot and a gamble.
- The client cannot leak an experiment. Assignment is a server decision; the SDK receives one expanded flow.
- Old binaries keep up. A user who installed months ago renders a flow written today.
- One source of truth. One document, one renderer, so a native app and a Flutter app cannot draw it differently.