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:
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
Create your steps configuration (e.g.,
onboardingSteps.ts
):tsx19 lines1// 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]
Create a client onboarding UI component:
tsx37 lines1// 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}
Wrap your UI with
OnboardingProvider
in a client component:tsx17 lines1// 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
Create your steps configuration (e.g.,
onboardingSteps.ts
):tsx19 lines1// 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]
Create your onboarding UI component:
tsx35 lines1// 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}
Wrap your UI with
OnboardingProvider
in your page component:tsx15 lines1// 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 thelocalStoragePersistence
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 orgetServerSideProps
. - Hydration:
If you need to pre-populate onboarding context from the server, pass it asinitialContext
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
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 theuseOnboarding
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.