Optional onboarding flow for new users to complete their profile before accessing the dashboard. Toggle with NEXT_PUBLIC_ONBOARDING_ENABLED.

Onboarding Flow

Onboarding primarily collects profile fields after checkout. In B2B, the workspace is normally created earlier by the automatic bootstrap so billing can target a workspace account. The middleware does not block /checkout only because a profile is incomplete; the profile gate decision is made in checkout/success/page.tsx.

  1. User signs up — magic link / OTP code / OAuth. The database trigger creates the personal account.
  2. B2B workspace bootstrap — if businessModel is 'b2b', server-side auth/checkout paths call ensureWorkspaceForUser() so the subscription has a workspace target. /onboarding/workspace remains a fallback if bootstrap fails.
  3. Plan + payment — the user continues to /checkout from the pending-checkout cookie. Stripe checkout completes, or /api/billing/subscribe-free creates the free subscription on the correct account.
  4. Success page decisioncheckout/success/page.tsx reads profile.onboarding_completed. If false, the success CTA leads to /onboarding; otherwise straight to a dashboard (workspace-manager rule: /org-dashboard for owners/admins, else /private-dashboard).
  5. Form submissionOnboardingForm posts first/last name + optional birthday + phone to POST /api/user/onboarding, where the server applies Zod validation, sanitization, CSRF/rate-limit protection, and service-role persistence. Signup analytics conversion and the referral-attribute call remain fire-and-forget.
  6. Post-submit redirect — routes the user to the appropriate dashboard via the same workspace-manager rule. If a B2B user still has no workspace, they are sent back to /onboarding/workspace.
B2B safety net: the (private)/layout.tsx server-side guard also redirects any B2B user without a workspace membership to /onboarding/workspace. This catches users who skipped onboarding, accepted the cookie cache, or were imported via SQL.

Collected Fields

Field Required Description
First Name Yes User's first name — Zod-validated min(2).max(50) chars.
Last Name Yes User's last name — Zod-validated min(2).max(50) chars.
Phone No Contact phone number (optional).
Birthday No Date of birth (optional) — minimum age 13 (Zod refinement against the current date).
Pending-checkout cookie

If the user reached /onboarding with a bsk_pending_checkout cookie set (the "clicked a plan before signing in" case), the post-submit redirect goes to /checkout instead of the dashboard. Otherwise the workspace-manager rule applies: owners/admins of any workspace land on /org-dashboard, everyone else on /private-dashboard.

Skipping Onboarding

When NEXT_PUBLIC_ONBOARDING_ENABLED=false:

  • Middleware skips profile completeness check
  • Users go directly to dashboard after auth
  • Profile can be completed later in My Account page