Headless Onboarding for React. No Overlays. Full Control.

State management, analytics, and persistence built-in. Skip the tour library limitations. Deploy custom flows in minutes.

WelcomeStep.tsx
stepsConfig.ts
function WelcomeStep() {
const { next } = useOnboarding()
return (
<div>
<button onClick={() => next()}>Next</button>
</div>
)
}

Core concepts

Defining steps

Steps are the building blocks of your onboarding flow in OnboardJS. Each step represents a screen, question, or action the user will encounter. You define your steps as an array of objects, each with a unique id, a type, and a payload describing the content or behavior of the step.


How to define Onboarding Steps

Here’s what a typical step looks like:

tsx
12 lines
1import { OnboardingStep } from '@onboardjs/core'
2
3const step: OnboardingStep = {
4  id: 'welcome', // Unique identifier for this step
5  payload: {
6    title: 'Welcome!',
7    mainText: "Let's get started.",
8    ctaButtonText: 'Next',
9  },
10  nextStep: 'profile', // (Optional) The id of the next step
11  previousStep: null, // (Optional) The id of the previous step
12}

Defining multiple steps

tsx
37 lines
1import { OnboardingStep } from '@onboardjs/core'
2
3const steps: OnboardingStep[] = [
4  {
5    id: 'welcome',
6    payload: {
7      title: 'Welcome to the App!',
8      mainText: "Let's get you set up.",
9      ctaButtonText: 'Start',
10    },
11    nextStep: 'choose-role',
12  },
13  {
14    id: 'choose-role',
15    type: 'SINGLE_CHOICE',
16    payload: {
17      question: 'What is your role?',
18      dataKey: 'userRole',
19      options: [
20        { id: 'dev', label: 'Developer', value: 'developer' },
21        { id: 'designer', label: 'Designer', value: 'designer' },
22      ],
23    },
24    nextStep: 'finish',
25    previousStep: 'welcome',
26  },
27  {
28    id: 'finish',
29    payload: {
30      title: "You're all set!",
31      mainText: 'Enjoy using the app.',
32      ctaButtonText: 'Done',
33    },
34    previousStep: 'choose-role',
35    nextStep: null, // End of flow
36  },
37]

Advanced Step Features

Dynamic Navigation

You can use a function for nextStep or previousStep to determine the next step based on the current context:

tsx
5 lines
1{
2  id: "figma-choose-role",
3  payload: { /* ... */ },
4  nextStep: (context) => context.flowData.userRole === "developer" ? "dev-setup" : "designer-setup",
5}

Conditional Steps

Use the condition property to show or skip a step based on the context:

tsx
10 lines
1{
2  id: "dev-setup",
3  payload: { title: "Developer Setup" },
4  condition: (context) => context.flowData.userRole === "developer",
5},
6{
7  id: "admin-setup",
8  payload: { title: "Admin Setup" },
9  condition: (context) => context.flowData.userRole === "admin",
10}

Best Practices

  • Unique IDs: Every step must have a unique id.
  • Keep it modular: Break complex flows into small, focused steps.
  • Use flowData: Store user answers and flags in context.flowData for use in navigation and conditions.
  • Use condition for personalization: Show or skip steps based on previous answers.

Next:

Previous
Onboarding config