Quickstart
Install Cairn, define a flow, and render your first guided onboarding in a few minutes.
Quickstart
Install
npm i cairn-react
# the React package re-exports the core, so this is all you needFor a non-React app or a custom renderer, install just the engine:
npm i cairn-core1. Define a flow
A flow is a list of steps. Each step knows where to go next — and
next can be a function that branches on live context.
import { defineFlow } from "cairn-react";
const onboarding = defineFlow<{ hasTeam: boolean }>({
id: "onboarding",
initialContext: { hasTeam: false },
steps: [
{
id: "welcome",
next: "profile",
meta: { target: "#logo", title: "Welcome 👋", body: "Let's get you set up." },
},
{
id: "profile",
// Branch: team users go to "invite", everyone else finishes.
next: (ctx) => (ctx.hasTeam ? "invite" : null),
meta: { target: "#profile", title: "Your profile" },
},
{
id: "invite",
next: null, // null ends the flow
meta: { target: "#invite", title: "Invite your team" },
},
],
});2. Wrap your app
import { FlowProvider } from "cairn-react";
function App() {
return (
<FlowProvider flow={onboarding} options={{ autoStart: true }}>
<YourApp />
<Tour />
</FlowProvider>
);
}3. Render the current step
Cairn owns the logic; you own the UI. The meta bag carries whatever
your renderer needs (a target selector, a title, a body…).
import { useFlow } from "cairn-react";
function Tour() {
const { state, next, back, skip } = useFlow<{ hasTeam: boolean }>();
const step = state.currentStep;
if (!step) return null;
return (
<div data-step={step.id}>
<h3>{String(step.meta?.title ?? step.id)}</h3>
<small>
Step {state.stepIndex + 1} / {state.totalSteps}
</small>
<button onClick={back} disabled={state.history.length < 2}>Back</button>
<button onClick={next}>Next</button>
<button onClick={skip}>Skip</button>
</div>
);
}That's a complete, branching, multi-step onboarding. Next, learn the Core Concepts behind it.
Try the playground
The repo ships a live demo with a spotlight, branching toggle, and an event-stream panel:
pnpm play # → http://localhost:5173