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

Typed steps

On top of the basic step definition, OnboardJS provides several built-in step types with predefined payload structures to streamline common onboarding scenarios. These typed steps help ensure consistency and reduce boilerplate code.


Steps with Predefined Types

A step can have a predefined type to simplify its structure and behavior. Here are some common types:

  • INFORMATION: Displays informational content.
  • SINGLE_CHOICE: Presents a question with a single-choice answer.
  • MULTI_CHOICE: Presents a question with multiple-choice answers.
  • CUSTOM_COMPONENT: Renders a custom React component.

By default, if the type property is left out during step definition the type will be set to INFORMATION.

tsx
9 lines
1const step: OnboardingStep = {
2  id: 'welcome',
3  type: 'INFORMATION', // Step type (default)
4  payload: {
5    title: 'Welcome!',
6    mainText: "Let's get started.",
7    ctaButtonText: 'Next',
8  },
9}

Here’s what an advanced step with a different type looks like:

tsx
12 lines
1const step: OnboardingStep = {
2  id: 'persona-select',
3  type: 'SINGLE_CHOICE',
4  payload: {
5    question: 'What is your role?',
6    dataKey: 'userRole',
7    options: [
8      { id: 'dev', label: 'Developer', value: 'developer' },
9      { id: 'designer', label: 'Designer', value: 'designer' },
10    ],
11  },
12}

Advanced Typed Step Features

Another advantage of using typed steps is the ability to use the same UI component for all steps of a specific type. This can greatly simplify your component logic and ensure a consistent look and feel.

Type specific UI Components

When you have multiple steps of the same type, you can create a dedicated UI component for that type.

For example:

Having both the welcome and thank-you steps as INFORMATION type steps, you can create a dedicated UI component for them.

typescript
18 lines
1{
2  id: 'welcome',
3  type: 'INFORMATION',
4  payload: {
5    title: 'Welcome!',
6    mainText: "Let's get started.",
7    ctaButtonText: 'Next',
8  },
9},
10{
11  id: 'thank-you',
12  type: 'INFORMATION',
13  payload: {
14    title: 'Thank You!',
15    mainText: "We're glad to have you on board.",
16    ctaButtonText: 'Finish',
17  },
18}

Then in your component registry definition you can create a mapping of type for the new component.

tsx
3 lines
1const componentRegistry = {
2  INFORMATION: CustomInformationStep,
3}

And finally, pass your steps and componentRegistry to the OnboardingProvider.

tsx
1 lines
1<OnboardingProvider steps={steps} componentRegistry={componentRegistry}>

Custom Step Types

In addition to the built-in step types, you can define your own custom step types to handle specific use cases in your onboarding flow.

Use the CUSTOM_COMPONENT type to create a step that should be rendered in a custom but reusable way. Then specify the componentKey property in the step payload to have that component rendered.

For example:

The steps definition.

tsx
20 lines
1{
2  id: 'custom-step',
3  type: 'CUSTOM_COMPONENT',
4  payload: {
5    componentKey: 'MyCustomComponent',
6    props: {
7      // Custom props for your component
8    },
9  },
10},
11{
12  id: 'custom-step-2',
13  type: 'CUSTOM_COMPONENT',
14  payload: {
15    componentKey: 'MyCustomComponent',
16    props: {
17      // Custom props for your component
18    },
19  },
20}

The component registry maps the componentKey to the actual React component that should be rendered for that step.

tsx
5 lines
1import { MyCustomComponent } from '@/your-codebase'
2
3const componentRegistry = {
4  MyCustomComponent: MyCustomComponent,
5}

Next:

Previous
Defining steps