Manual installation

TanStack Start

Wire the Sunboard React SDK into a TanStack Start app by hand.

Most people don't need this

sunboard init does all of this automatically — see the Quick start. Follow this page if you'd rather wire things by hand, or want to understand exactly what init changes.

TanStack Start is Vite-based, so the setup is the same as Vite — the one difference is where you mount the provider: your root route, src/routes/__root.tsx, instead of a client entry.

Install the SDK

npm install @sunboard/react
pnpm add @sunboard/react
yarn add @sunboard/react
bun add @sunboard/react

Add your publishable key

Like Vite, TanStack Start exposes VITE_-prefixed env vars to the browser. Put your project's runtime key in .env.local:

.env.local
VITE_SUNBOARD_KEY=pk_live_xxx

Create the runtime wrapper

This component reads the current location and renders the Sunboard widgets. It uses TanStack Router's useLocation and useRouter so tour route changes stay client-side.

src/sunboard-provider.tsx
import { SunboardProvider, Sunboard } from "@sunboard/react";
import { useLocation, useRouter } from "@tanstack/react-router";
import type { ReactNode } from "react";

export function SunboardRuntime({ children }: { children: ReactNode }) {
  const router = useRouter();
  const location = useLocation();
  const route = `${location.pathname}${location.searchStr}`;

  return (
    <SunboardProvider
      publishableKey={import.meta.env.VITE_SUNBOARD_KEY}
      // Replace with your real authenticated user.
      user={{
        id: "demo-user",
        email: "demo@example.com",
        group: "demo",
      }}
      route={route}
      // history.push keeps navigation client-side without TanStack's typed-route
      // constraints; swap to router.navigate({ to }) if you prefer typed routes.
      navigate={(url) => router.history.push(url)}
    >
      {children}
      <Sunboard.Checklist />
      <Sunboard.Hotspots />
      <Sunboard.Tooltips />
      <Sunboard.Tour />
    </SunboardProvider>
  );
}

Router context

useLocation / useRouter only work inside the router, so the wrapper must live below your root route — mounting it in __root.tsx (next step) satisfies this.

Mount it in your root route

Import the Sunboard stylesheet before your own global CSS, then wrap the {children} your root document renders (inside <body>).

src/routes/__root.tsx
import "@sunboard/react/styles.css";
import appCss from "../styles/app.css?url";
import { createRootRoute, Outlet, Scripts } from "@tanstack/react-start";
import { SunboardRuntime } from "../sunboard-provider";

export const Route = createRootRoute({
  head: () => ({
    links: [{ rel: "stylesheet", href: appCss }],
  }),
  component: RootComponent,
});

function RootComponent() {
  return (
    <RootDocument>
      <Outlet />
    </RootDocument>
  );
}

function RootDocument({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        <SunboardRuntime>{children}</SunboardRuntime>
        <Scripts />
      </body>
    </html>
  );
}

Match your project's root

The exact shape of __root.tsx varies by TanStack Start version. The only thing that matters is that <SunboardRuntime> wraps the {children} / <Outlet /> your root renders. Keep your existing imports and head config.

Wire your real user

The wrapper ships a placeholder user. Replace it with your authenticated user so segments and analytics are accurate. Only id is required; anything you put under properties is available for segment targeting:

user={{
  id: currentUser.id,
  email: currentUser.email,
  group: currentUser.plan, // optional cohort, e.g. "trial" / "pro"
  properties: {
    // Any custom attributes you want to target on.
    role: currentUser.role,
    signupDate: currentUser.createdAt,
    workflowsCreated: currentUser.workflowCount,
  },
}}

Verify

Run your dev server. It uses the pk_test_ key, so once you've deployed a spec to the sandbox the checklist appears. Deploy one with /sunboard.deploy, or run sunboard doctor to check the wiring.

Next steps

On this page