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.
- User signs up — magic link / OTP code / OAuth. The database trigger creates the personal account.
- B2B workspace bootstrap — if
businessModelis'b2b', server-side auth/checkout paths callensureWorkspaceForUser()so the subscription has a workspace target./onboarding/workspaceremains a fallback if bootstrap fails. - Plan + payment — the user continues to
/checkoutfrom the pending-checkout cookie. Stripe checkout completes, or/api/billing/subscribe-freecreates the free subscription on the correct account. - Success page decision —
checkout/success/page.tsxreadsprofile.onboarding_completed. Iffalse, the success CTA leads to/onboarding; otherwise straight to a dashboard (workspace-manager rule:/org-dashboardfor owners/admins, else/private-dashboard). - Form submission —
OnboardingFormposts first/last name + optional birthday + phone toPOST /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. - 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.
(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). |
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