Stop Reinventing the Onboarding Wheel. Start Building.

Your users need smooth flows. You need clean code, faster. OnboardJS handles the messy state stuff so that you can focus on building.

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

Next.js

Using OnboardJS in a Next.js Project

OnboardJS integrates smoothly with both the App Router (app/ directory) and the Pages Router (pages/ directory) in Next.js projects. This overview explains how to set up OnboardJS in either structure, with best practices for state management, persistence, and SSR considerations.


Installation

Install the React SDK and core engine:

bash
1 lines
1npm install @onboardjs/react @onboardjs/core

Using OnboardJS with the App Router (app/ Directory)

The App Router uses React Server Components by default, but OnboardJS should be used in Client Components only.

Basic Setup

  1. Create your steps configuration (e.g., onboardingSteps.ts):

    tsx
    19 lines
    1// app/onboardingSteps.ts
    2export const steps = [
    3  {
    4    id: 'welcome',
    5    type: 'INFORMATION',
    6    payload: { title: 'Welcome!' },
    7    nextStep: 'profile',
    8  },
    9  {
    10    id: 'profile',
    11    type: 'SINGLE_CHOICE',
    12    payload: {
    13      question: 'Your role?',
    14      options: [{ id: 'dev', label: 'Developer', value: 'dev' }],
    15    },
    16    nextStep: 'done',
    17  },
    18  { id: 'done', type: 'INFORMATION', payload: { title: 'All set!' } },
    19]
    
  2. Create a client onboarding UI component:

    tsx
    37 lines
    1// app/onboarding/OnboardingUI.tsx
    2'use client'
    3
    4import { useOnboarding } from '@onboardjs/react'
    5
    6export function OnboardingUI() {
    7  const { currentStep, state, next, previous } = useOnboarding()
    8
    9  if (state.isCompleted) return <div>Onboarding complete!</div>
    10
    11  const Component =
    12    yourComponentRegistry[
    13      currentStep.payload.componentKey ?? currentStep.type ?? currentStep.id
    14    ]
    15
    16  if (!Component) {
    17    return <div>Unknown step</div>
    18  }
    19
    20  return (
    21    <div>
    22      <Component
    23        payload={currentStep.payload}
    24        coreContext={state.context}
    25        onDataChange={() => {}}
    26      />
    27      <div>
    28        <button onClick={previous} disabled={!state.canGoPrevious}>
    29          Back
    30        </button>
    31        <button onClick={next} disabled={!state.canGoNext}>
    32          Next
    33        </button>
    34      </div>
    35    </div>
    36  )
    37}
    
  3. Wrap your UI with OnboardingProvider in a client component:

    tsx
    17 lines
    1// app/onboarding/page.tsx
    2'use client'
    3
    4import { OnboardingProvider } from '@onboardjs/react'
    5import { steps } from '../onboardingSteps'
    6import { OnboardingUI } from './OnboardingUI'
    7
    8export default function OnboardingPage() {
    9  return (
    10    <OnboardingProvider
    11      steps={steps}
    12      localStoragePersistence={{ key: 'onboardjs:my-flow' }}
    13    >
    14      <OnboardingUI />
    15    </OnboardingProvider>
    16  )
    17}
    

Tips:

  • Always use 'use client' at the top of any file that uses OnboardJS hooks or context.
  • You can place the provider at any level (e.g., in a layout or a specific page).

Using OnboardJS with the Pages Router (pages/ Directory)

The Pages Router uses classic React components and works seamlessly with OnboardJS.

Basic Setup

  1. Create your steps configuration (e.g., onboardingSteps.ts):

    tsx
    19 lines
    1// pages/onboardingSteps.ts
    2export const steps = [
    3  {
    4    id: 'welcome',
    5    type: 'INFORMATION',
    6    payload: { title: 'Welcome!' },
    7    nextStep: 'profile',
    8  },
    9  {
    10    id: 'profile',
    11    type: 'SINGLE_CHOICE',
    12    payload: {
    13      question: 'Your role?',
    14      options: [{ id: 'dev', label: 'Developer', value: 'dev' }],
    15    },
    16    nextStep: 'done',
    17  },
    18  { id: 'done', type: 'INFORMATION', payload: { title: 'All set!' } },
    19]
    
  2. Create your onboarding UI component:

    tsx
    35 lines
    1// pages/onboarding/OnboardingUI.tsx
    2import { useOnboarding } from '@onboardjs/react'
    3
    4export function OnboardingUI() {
    5  const { currentStep, state, next, previous } = useOnboarding()
    6
    7  if (state.isCompleted) return <div>Onboarding complete!</div>
    8
    9  const Component =
    10    yourComponentRegistry[
    11      currentStep.payload.componentKey ?? currentStep.type ?? currentStep.id
    12    ]
    13
    14  if (!Component) {
    15    return <div>Unknown step</div>
    16  }
    17
    18  return (
    19    <div>
    20      <Component
    21        payload={currentStep.payload}
    22        coreContext={state.context}
    23        onDataChange={() => {}}
    24      />
    25      <div>
    26        <button onClick={previous} disabled={!state.canGoPrevious}>
    27          Back
    28        </button>
    29        <button onClick={next} disabled={!state.canGoNext}>
    30          Next
    31        </button>
    32      </div>
    33    </div>
    34  )
    35}
    
  3. Wrap your UI with OnboardingProvider in your page component:

    tsx
    15 lines
    1// pages/onboarding/index.tsx
    2import { OnboardingProvider } from '@onboardjs/react'
    3import { steps } from '../onboardingSteps'
    4import { OnboardingUI } from './OnboardingUI'
    5
    6export default function OnboardingPage() {
    7  return (
    8    <OnboardingProvider
    9      steps={steps}
    10      localStoragePersistence={{ key: 'onboardjs:my-flow' }}
    11    >
    12      <OnboardingUI />
    13    </OnboardingProvider>
    14  )
    15}
    

Persistence and SSR Considerations

  • Persistence:
    Use the localStoragePersistence prop for client-side persistence, or provide custom handlers for backend persistence (e.g., Supabase, Neon).
  • SSR:
    OnboardJS is designed for client-side onboarding flows. Do not use OnboardJS hooks or context in server components or getServerSideProps.
  • Hydration:
    If you need to pre-populate onboarding context from the server, pass it as initialContext to the provider.

Advanced: Custom Step Components and Dynamic Flows

  • Use a componentRegistry map to map step types or keys to your own React components.
  • You can generate steps dynamically based on user data or API responses before rendering the provider.

Example: Integrating with Supabase in Next.js

tsx
36 lines
1// app/onboarding/page.tsx or pages/onboarding/index.tsx
2'use client';
3
4import { OnboardingProvider } from '@onboardjs/react';
5import { steps } from '../onboardingSteps';
6import { OnboardingUI } from './OnboardingUI';
7import { supabase } from '../lib/supabaseClient';
8
9export default function OnboardingPage() {
10  return (
11    <OnboardingProvider
12      steps={steps}
13      customOnDataLoad={async () => {
14        const { data } = await supabase
15          .from('onboarding')
16          .select('context')
17          .eq('user_id', /* your user id */)
18          .single();
19        return data?.context || undefined;
20      }}
21      customOnDataPersist={async (context) => {
22        await supabase
23          .from('onboarding')
24          .upsert({ user_id: /* your user id */, context });
25      }}
26      customOnClearPersistedData={async () => {
27        await supabase
28          .from('onboarding')
29          .delete()
30          .eq('user_id', /* your user id */);
31      }}
32    >
33      <OnboardingUI />
34    </OnboardingProvider>
35  );
36}

Summary

  • OnboardJS works with both the App Router and Pages Router in Next.js.
  • Always use OnboardJS in client components.
  • Wrap your onboarding UI with OnboardingProvider and use the useOnboarding hook for state and actions.
  • Use localStorage or custom persistence as needed.
  • For advanced flows, leverage the component registry and dynamic step generation.

For more, see the Quickstart Guide and React SDK Overview.

Previous
Examples & Recipes