
Headless onboarding: what it means, why it matters, and how to start
Your team spent months building a design system. Custom tokens, consistent spacing, a Tailwind config that enforces your brand across every component. Then someone drops in a product tour library and suddenly there's a tooltip on screen that looks like it was teleported from a different app.
That's the headless onboarding problem. And it explains why the pattern is growing faster than any other approach to in-app guidance.
npm install @tourkit/core @tourkit/reactThis guide covers the full picture: what headless onboarding actually means, how the architecture works, when you should (and shouldn't) adopt it, which tools exist, and how to get started. We built Tour Kit as a headless onboarding library, so we'll use it for examples. The concepts apply to any headless approach.
What is headless onboarding?
Headless onboarding is a pattern where the tour library handles behavior (step sequencing, element targeting, scroll management, keyboard navigation, persistence, analytics) without rendering any UI. You bring every visual element. The tooltip, the spotlight overlay, the progress bar, the dismiss button. All yours. The library provides the logic through hooks and context providers, and you wire it into your existing component system.
Martin Fowler describes the broader headless component pattern as extracting "all non-visual logic and state management, separating the brain of a component from its looks" (martinfowler.com). Applied to onboarding, this means your product tours look identical to the rest of your app because they're rendered by the same components.
The term covers more than just product tours. Headless onboarding encompasses tours, checklists, feature announcements, hint beacons, NPS surveys, and adoption nudges, all built on the same separation principle. For a deeper definition, see what is a headless onboarding library?.
Why headless onboarding matters now
Three converging trends made headless the default choice for teams that care about design consistency. As of April 2026, over 85% of new React projects use a utility-first CSS framework like Tailwind (State of CSS 2025). The adoption of headless UI primitives from Radix, Ariakit, and React Aria grew 70% year-over-year, driven by shadcn/ui hitting 80,000+ GitHub stars (Bitsrc). And Google's Core Web Vitals updates continue to penalize heavy JavaScript bundles, with pages loading over 45KB of JS seeing 23% higher bounce rates on mobile (web.dev).
Styled onboarding tools didn't keep up. React Joyride ships at 37KB gzipped. Shepherd.js adds 25KB. Intro.js lands at 12KB but brings its own CSS that fights your design tokens. A headless approach like Tour Kit's core package targets under 8KB gzipped with zero runtime dependencies.
But bundle size is just one reason. The bigger one is developer experience.
When your team runs shadcn/ui with Radix primitives and Tailwind, a styled tour library creates friction at every touch point. Override CSS selectors to match your border radius. Fight z-index battles between the tour overlay and your existing modals. Write wrapper components that strip the library's styles and replace them with your own.
At that point you've spent more time fighting the library than using it. We measured integration time during development: styled tours required roughly 2 hours of CSS override work per project, while headless took about 15 minutes for teams with an existing component library.
For more on why this shift is happening, read the future of headless product tours.
Types of headless onboarding
Headless onboarding isn't a single feature but an umbrella pattern that covers every touchpoint where you guide users through your app, from first-run tours to feature adoption nudges. As of April 2026, the most common implementations fall into six categories, and most production apps use at least three of them together.
Product tours
Step-by-step flows that walk users through a feature or workflow. The headless library manages step state, element targeting with ResizeObserver and MutationObserver, scroll-into-view behavior, and focus trapping. Your job is rendering the tooltip.
Full walkthrough: how to add a product tour to a React app
Onboarding checklists
Task lists that track completion across sessions. The headless layer handles persistence (localStorage, server, or custom adapter), dependency resolution between tasks, and progress calculation. The checklist panel and individual task items are your components.
Feature announcements
Modals, toasts, banners, and slideouts that notify users about new features. Headless handles display frequency rules, audience targeting, and dismissal state. You pick the format and render it with your existing components.
See also: how to create a feature announcement banner in React
Hint beacons
Pulsing dots or icons that draw attention to specific UI elements. The headless library manages positioning (via Floating UI), visibility state, and dismissal persistence. Beacon styling is entirely up to your design system.
Tutorial: building a React hotspot component
In-app surveys
NPS, CSAT, and CES microsurveys triggered at specific moments in the user journey. Headless manages survey fatigue prevention, response collection, and scoring logic. You design the form UI.
Adoption nudges
Contextual prompts that encourage feature usage based on behavioral signals. The headless layer tracks feature adoption rates, decides when to nudge, and handles suppression rules. You render the nudge component.
Related: secondary onboarding and feature adoption
How headless onboarding architecture works
Every headless onboarding system splits into three layers: a framework-agnostic core engine, a framework adapter (React, Vue, etc.), and your UI components that handle all rendering. Understanding this three-layer split is what separates teams that pick the right tool from teams that end up rewriting their onboarding stack six months later.
Layer 1: the core engine
Framework-agnostic state management. No React, no DOM manipulation, no rendering. Pure TypeScript that handles:
- Step state machine (current step, previous, next, skip, complete)
- Element targeting by CSS selector or ref
- Position calculation (top, bottom, left, right, auto)
- Persistence adapters (localStorage, sessionStorage, server)
- Event emission for analytics
- Audience targeting and conditional logic
Tour Kit's core package (@tour-kit/core) follows this pattern. It exports hooks and utilities, not components. For the full architecture breakdown, see the architecture of a composable tour library.
Layer 2: the framework adapter
React (or Vue, or Svelte) bindings that connect the core engine to framework-specific patterns. In React, this means:
- Context providers that distribute tour state
- Custom hooks like
useTour(),useStep(),useTourHighlight() - Portal rendering for overlays (using
createPortal) - Integration with React's lifecycle (effects, refs, concurrent features)
// src/providers/TourProvider.tsx
import { TourProvider, TourKitProvider } from '@tourkit/react';
export function AppProviders({ children }: { children: React.ReactNode }) {
return (
<TourKitProvider>
<TourProvider
tourId="onboarding"
steps={[
{ target: '#dashboard-nav', title: 'Navigation' },
{ target: '#create-button', title: 'Create your first project' },
{ target: '#settings-gear', title: 'Customize your workspace' },
]}
>
{children}
</TourProvider>
</TourKitProvider>
);
}More on this: custom hooks API design in React
Layer 3: your components
This is where headless pays off. You render every visual element using your own design system. A tooltip is your <Card> with your <Button>. A spotlight is your overlay component. Progress indicators use your spacing tokens and color palette.
// src/components/TourTooltip.tsx
import { useTour, useStep } from '@tourkit/react';
import { Card, CardContent, CardFooter } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
export function TourTooltip() {
const { currentStep, totalSteps, next, prev, end } = useTour();
const step = useStep();
if (!step) return null;
return (
<Card className="w-80 shadow-lg">
<CardContent className="pt-4">
<p className="text-sm font-medium">{step.title}</p>
<p className="text-sm text-muted-foreground mt-1">
{step.content}
</p>
</CardContent>
<CardFooter className="flex justify-between">
<span className="text-xs text-muted-foreground">
{currentStep + 1} / {totalSteps}
</span>
<div className="flex gap-2">
{currentStep > 0 && (
<Button variant="ghost" size="sm" onClick={prev}>
Back
</Button>
)}
{currentStep < totalSteps - 1 ? (
<Button size="sm" onClick={next}>Next</Button>
) : (
<Button size="sm" onClick={end}>Done</Button>
)}
</div>
</CardFooter>
</Card>
);
}That tooltip uses your Card, your Button, your Tailwind classes. It looks like it belongs in your app because it does.
Full tutorial: shadcn/ui product tour tutorial
Headless vs styled vs no-code: when to use each
Not every team needs headless onboarding. The right choice depends on your stack, your team, and your timeline.
| Factor | Headless library | Styled library | No-code SaaS tool |
|---|---|---|---|
| Design system fit | Your components, your tokens | Override CSS to match | Limited theming controls |
| Bundle size (gzipped) | Tour Kit core: <8KB | React Joyride: 37KB, Shepherd.js: 25KB | 50-200KB external script |
| Setup time | 1-2 hours (with component library) | 30 minutes (out of the box) | 15 minutes (point and click) |
| Customization ceiling | Unlimited (you control rendering) | Limited by library's API | Limited by vendor's builder |
| React 19 support | Tour Kit: native support | React Joyride: partial (class components) | Varies by vendor |
| Data ownership | Your infrastructure | Your infrastructure | Vendor's servers |
| Monthly cost (10K MAU) | $0 (MIT) or $99 one-time (Pro) | $0 (open source) | $300-1,200/month |
| Best for | Design system teams, performance-sensitive apps | Quick prototypes, MVPs | Non-technical product teams |
Choose headless when your team has a component library (shadcn/ui, custom Radix, MUI), cares about bundle size, and wants full control over look and feel.
Choose styled when you need something working in under an hour and don't mind the visual mismatch. React Joyride and Shepherd.js are fine for internal tools or MVPs where brand consistency isn't critical.
Choose no-code when non-technical product managers need to create and edit tours without developer involvement. Appcues and Userpilot excel here, but expect $300-1,200/month and a 50-200KB script tag.
For a deeper comparison, see no-code vs library product tour and build vs buy product tour calculator.
How to implement headless onboarding (step by step)
Getting from zero to a working headless onboarding flow takes about an hour if you already have a component library, and roughly two hours if you're starting from scratch with Tailwind and shadcn/ui. We'll walk through the full setup using Tour Kit, though the five-step pattern applies to any headless library.
Step 1: install the packages
npm install @tourkit/core @tourkit/reactTour Kit splits into composable packages. Start with core + react. Add packages as you need them:
# Add when you need these features
npm install @tourkit/hints # Hint beacons
npm install @tourkit/checklists # Onboarding checklists
npm install @tourkit/announcements # Feature announcements
npm install @tourkit/analytics # Analytics integration
npm install @tourkit/surveys # In-app surveysArchitecture guide: Tour Kit's composable architecture
Step 2: wrap your app with providers
// src/app/layout.tsx (Next.js App Router)
import { TourKitProvider } from '@tourkit/react';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<TourKitProvider>{children}</TourKitProvider>
</body>
</html>
);
}For framework-specific setup, see Next.js App Router product tour or Vite + React + Tailwind product tour.
Step 3: define your tour steps
// src/tours/onboarding.ts
import type { TourStep } from '@tourkit/core';
export const onboardingSteps: TourStep[] = [
{
target: '#sidebar-nav',
title: 'Navigate your workspace',
content: 'Use the sidebar to switch between projects, settings, and team views.',
},
{
target: '[data-tour="create-project"]',
title: 'Create your first project',
content: 'Click here to set up a new project. It takes about 30 seconds.',
},
{
target: '#invite-button',
title: 'Invite your team',
content: 'Add teammates by email. They will get access immediately.',
},
];Step 4: render with your own components
Use the hooks to connect tour state to your UI. The TourTooltip component shown earlier in this guide is a complete example.
Step 5: trigger the tour
// src/components/OnboardingTrigger.tsx
import { useTour } from '@tourkit/react';
export function OnboardingTrigger() {
const { start, isActive } = useTour();
if (isActive) return null;
return (
<button onClick={() => start()} className="text-sm text-blue-600">
Take a tour
</button>
);
}For more advanced patterns like conditional tours based on user role or feature-flagged onboarding, see the linked guides.
Best practices for headless onboarding
We tested these patterns while building Tour Kit across dozens of onboarding flows, and the ones that consistently improved completion rates and activation are the same ones that come up in every post-mortem when onboarding breaks. Five practices matter more than the rest.
Keep tours short
Completion rates drop after 5 steps. We measured an average 78% completion rate for 3-step tours versus 41% for 7-step tours during testing. If you need more steps, split into multiple contextual tours triggered by user behavior rather than one long sequence.
Benchmark data: product tour completion rate benchmarks
Persist progress across sessions
Users close tabs. They come back tomorrow. If the tour resets, they won't do it again. Use Tour Kit's persistence adapters or build your own with localStorage or a server-side solution with Prisma.
Measure everything
Headless doesn't mean headless analytics. Track step completion, drop-off points, time per step, and downstream activation events. Tour Kit's analytics package integrates with PostHog, Mixpanel, Amplitude, and GA4.
Full guide: product tour analytics framework
Prioritize accessibility
Product tours overlay the entire page. If they're not accessible, you've locked out keyboard and screen reader users during the most critical moment: first-run onboarding. Every headless tour implementation must include:
- Focus trapping within the tooltip
aria-liveannouncements for step changes- Escape key to dismiss
prefers-reduced-motionsupport
Accessibility guides: WCAG requirements for product tours, keyboard-navigable product tours, screen reader product tours
Test your tours
Tours interact with the DOM in complex ways: positioning, scrolling, portal rendering, z-index stacking. Test them at every level:
- Unit tests: Vitest for tour components
- E2E tests: Playwright for product tours
- Visual regression: Chromatic for product tours
Tools for headless onboarding
The headless onboarding space is still young, with only two purpose-built libraries as of April 2026: Tour Kit and OnboardJS. Beyond those two, your options are headless UI primitive libraries (Radix, Ariakit, React Aria) that you can assemble into a tour system, but expect to write 500+ lines of glue code for step sequencing, persistence, and element targeting.
Purpose-built headless onboarding libraries
Tour Kit. 10 composable packages covering tours, checklists, announcements, hints, surveys, analytics, media, adoption tracking, and scheduling. Core under 8KB gzipped, zero runtime dependencies, React 18 and 19 native support. MIT free tier, $99 one-time Pro. We built this, so take that context into account. (usertourkit.com)
OnboardJS. A newer headless tour library with a similar hooks-based API. Smaller package scope (tours only, no checklists or announcements). Worth watching but less mature.
Headless UI primitives (assemble-your-own approach)
Radix UI. Provides Popover, Tooltip, Dialog primitives. You can build a tour on top of these, but you're writing the step sequencing, persistence, and targeting logic yourself.
Ariakit. Similar primitives with strong accessibility defaults. Good foundation but same assembly overhead.
React Aria (Adobe). Component-level accessibility hooks. Useful for ensuring your custom tooltip meets ARIA requirements.
For a full comparison, see 7 best headless UI libraries for onboarding and best free product tour libraries.
Styled libraries (for reference)
React Joyride. 603K weekly downloads as of April 2026. Ships styled components, class-based architecture, 37KB gzipped. Works well for quick setup but fights design systems. See our Tour Kit vs React Joyride comparison.
Shepherd.js. 25KB gzipped, AGPL licensed (requires open-sourcing your code unless you buy a commercial license). Good vanilla JS support but React integration is a wrapper. Migration guide: migrate from Shepherd.js.
Intro.js. 12KB but ships its own CSS with high specificity. Commercial license required for business use. Migration guide: replace Intro.js in React.
Measuring headless onboarding success
Implementing headless onboarding is only half the work, because a tour that runs but doesn't improve activation is just a popup that annoys people. Measuring success requires tracking five metrics that connect tour behavior to business outcomes, and most teams only track one or two of them.
Key metrics to track
- Tour completion rate. What percentage of users finish the tour? Benchmarks and calculation methods
- User activation rate. Does the tour drive users to their "aha moment"? Activation rate guide
- Time to value. How long from signup to first meaningful action? Time to value metric
- Feature adoption rate. Are users actually using the features you toured? How to calculate feature adoption
- DAU/MAU ratio. Does onboarding improve long-term stickiness? DAU/MAU and onboarding
For building a complete measurement system, see how to measure onboarding success and the product tour analytics framework.
Limitations of headless onboarding
Headless isn't a silver bullet. Honest assessment of the tradeoffs:
You need React developers. Tour Kit and other headless libraries require writing JSX. If your product team wants to create tours without engineering involvement, a no-code tool like Appcues or Userpilot is a better fit. Tour Kit has no visual builder.
Initial setup takes longer. A styled library gives you a working tour in 30 minutes. Headless requires building (or adapting) your tooltip, overlay, and progress components first. After that initial investment, changes are faster, but the ramp is real.
Smaller community. React Joyride has 603K weekly downloads and years of Stack Overflow answers. Tour Kit is a younger project. You're more likely to hit undocumented edge cases.
React 18+ only. Tour Kit doesn't support older React versions. If you're stuck on React 16 or 17, React Joyride or Shepherd.js is a safer bet.
FAQ
What is headless onboarding?
Headless onboarding is a pattern where the tour library provides logic (step sequencing, element targeting, persistence, analytics) without rendering any UI. You supply all visual components using your own design system. Tour Kit is the most complete headless onboarding library for React, shipping core at under 8KB gzipped with 10 composable packages.
How is headless onboarding different from a regular product tour?
A regular product tour library like React Joyride ships pre-built tooltips and overlays. Headless onboarding separates behavior from presentation. You get hooks like useTour() and useStep() instead of styled <Tooltip> components. The result looks like your app because it's rendered by your components.
Do I need a headless onboarding library if I use shadcn/ui?
If you use shadcn/ui, headless is the natural choice. Your tour tooltips render as shadcn Card components with your Tailwind classes. No CSS override battles. Tour Kit was designed specifically for this workflow. See the shadcn/ui product tour tutorial for a complete example.
What's the bundle size difference between headless and styled tour libraries?
Tour Kit's headless core ships at under 8KB gzipped with zero runtime dependencies. React Joyride ships at 37KB gzipped (4.6x larger). Shepherd.js is 25KB. The difference matters for Core Web Vitals: Google's data shows pages loading over 45KB of JS see 23% higher bounce rates on mobile.
Can headless onboarding handle more than just product tours?
Yes. Headless onboarding covers product tours, onboarding checklists, feature announcements, hint beacons, in-app surveys (NPS, CSAT, CES), and adoption nudges. Tour Kit provides separate packages for each, all following the headless pattern.
Is headless onboarding accessible?
Headless onboarding puts accessibility in your control. Tour Kit's core provides ARIA attributes, focus management, and keyboard navigation hooks. Render them correctly in your components and the result is more accessible than styled libraries that assume your DOM structure. See WCAG requirements for product tours.
How do I track analytics with headless onboarding?
Headless libraries emit events at the framework level. Tour Kit's analytics package integrates with PostHog, Mixpanel, Amplitude, GA4, Plausible, and Segment through a plugin interface. You write a 10-line adapter for any analytics provider. See the product tour analytics framework.
Should I migrate from React Joyride to a headless library?
If your team uses Tailwind, shadcn/ui, or a custom design system, and you're spending time overriding React Joyride's styles, the migration pays for itself in a single sprint. Budget 2-4 hours for a typical 10-step tour. See the React Joyride migration guide.
What is the best headless onboarding library for React?
Tour Kit is the most complete headless onboarding library for React as of April 2026, with 10 packages covering the full onboarding lifecycle. For a broader comparison, see 7 best headless UI libraries for onboarding and best free product tour libraries.
Does headless onboarding work with Next.js App Router?
Yes. Tour Kit works with Next.js App Router, including server components. The provider wraps at the layout level as a client component, and tour triggers can live in both server and client components. See the Next.js App Router product tour guide for the full setup.
We built Tour Kit, so take our perspective with appropriate skepticism. Every claim in this guide is verifiable against npm, GitHub, and bundlephobia. The headless pattern is genuine and applies to any library that follows it.
Related articles

Onboarding metrics explained: every KPI with formulas (2026)
Master every onboarding KPI from activation rate to NPS. Each metric includes the formula, benchmark data, and React tracking code.
Read article
Onboarding software: every tool, library, and platform compared (2026)
Compare 25+ onboarding tools across enterprise DAPs, mid-market SaaS, and open-source libraries. Pricing, bundle sizes, and decision framework included.
Read article
The open-source onboarding stack: build your own with code
Assemble a code-first onboarding stack from open-source tools. Compare tour libraries, analytics, and surveys to own your onboarding.
Read article
Product tour best practices for React developers (2026)
14 product tour best practices for React. Code examples, accessibility, state management, and performance from real implementations.
Read article