User Onboarding Flow
Status: CURRENT CODE-DERIVED VIEW, NOT A CANONICAL CONTRACT. Use this file
to trace the implemented onboarding path. If behavior conflicts with
docs/architecture/ARCHITECTURE_LOCK.md
or
docs/architecture/CONSOLIDATED_PRODUCT_PLATFORM_CONTRACT_v1.2.md,
the frozen contracts win.
Generated: July 29, 2026
Based on: Frontend onboarding implementation, Gateway onboarding service, Workspace API
High-Level Onboarding Flow
┌─────────────────────────────────────────────────────────────────────────────┐
│ ENTRY POINTS │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Direct │ │ Marketplace │ │
│ │ Sign-up │ │ Connector │ │
│ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │
│ └─────────────────┬─────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ Clerk OAuth │ │
│ │ (Google/ │ │
│ │ GitHub) │ │
│ └──────┬───────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────┐ │
│ │ Gateway: getOrCreateUser │ │
│ │ - Check existing user │ │
│ │ - Create new user if needed │ │
│ │ - Set onboarding intent │ │
│ └──────────────┬───────────────┘ │
│ │ │
│ ▼ │
└───────────────────────────────────┼───────────────────────────────────────────┘
│
┌───────────────────────────────────┼───────────────────────────────────────────┐
│ ONBOARDING SHELL (4 Steps) │
├───────────────────────────────────┼───────────────────────────────────────────┤
│ │ │
│ ┌─────────────────────────┼─────────────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Step 1 │ │ Step 2 │ │ Step 3 │ │
│ │ Welcome │ │ Profile │ │ Goals │ │
│ │ Use Case │ │ Industry/ │ │ Workspace │ │
│ │ Selection │ │ Department │ │ Creation │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
│ │ personal/work/business│ industry + department │ goal + workspace │
│ │ │ + company size │ name + type │
│ │ │ │ │
│ └───────────────────────┴───────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ Step 4 │ │
│ │ Complete │ │
│ │ Success + │ │
│ │ Redirect │ │
│ └──────┬───────┘ │
│ │ │
│ ┌───────────────────────┴───────────────────────┐ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Workbench │ │ Marketplace │ │
│ │ /app │ │ Connector │ │
│ └──────────────┘ │ Activation │ │
│ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Detailed Step-by-Step Flow
Step 1: Welcome (Use Case Selection)
Route: /onboarding
Component: WelcomeStep.tsx
User Selection:
- Personal - Organize personal work
- Work - Professional workflow
- Business - Company data & workflows
Data Collected:
{
useCase: "personal" | "work" | "business";
}
Backend Action:
- Calls
updateOnboardingState({ currentStep: "workspace", completedSteps: ["welcome"] }) - Stores preference in backend session
Domain Resolution:
personal → PERSONAL domain
work → Maps department to domain (SALES, MARKETING, REVOPS, etc.)
business → Maps department to domain (SALES, MARKETING, REVOPS, etc.)
Step 2: Profile (Industry & Department)
Route: /onboarding/profile
Component: ProfileStep.tsx
User Selection:
Industry Options (12):
- Technology / SaaS
- Professional Services
- Healthcare
- Education
- Manufacturing
- Automotive / Mobility
- Retail / E-commerce
- Financial Services
- Logistics / Supply Chain
- Media / Entertainment
- Government / Public Sector
- Other
Department Groups (4 categories):
- Revenue & Growth: Sales, Marketing, RevOps, Customer Success
- Technology: Engineering, Product Management, IT/Technology
- Operations: Operations, Supply Chain, Service Operations, Project Management
- Corporate: Finance/Accounting, Legal, Human Resources
Company Size:
- Just me, 2-10, 11-50, 51-200, 201-500, 500+
Data Collected:
{
industry: string,
department: string,
companySize: string
}
Spine Schema Init:
- When industry + department selected, triggers
handleSpineInit - Calls
updateOnboardingState({ currentStep: "configuration" }) - Configures adaptive Spine schema for domain
Domain Mapping:
SALES → SALES domain
MARKETING → MARKETING domain
CUSTOMER_SUCCESS → CUSTOMER_SUCCESS domain
ENGINEERING → PRODUCT_ENGINEERING domain
FINANCE → FINANCE domain
OPERATIONS → CUSTOMER_SUCCESS domain
// ... (full mapping in OnboardingShell.tsx)
Step 3: Goals & Workspace
Route: /onboarding/workspace
Component: GoalsStep.tsx
User Selection:
Primary Goals (5):
- Organize knowledge - Database icon
- Get insights - Sparkles icon
- Track context - Target icon
- Improve team - Users icon
- Automate work - Zap icon
Workspace Types (4):
- Company
- Department
- Client
- Project
Workspace Name: Free text input (default: "Acme Corp")
Data Collected:
{
goal: string,
workspaceName: string,
workspaceType: string
}
Backend Actions:
- Update Onboarding State:
await updateOnboardingState({
currentStep: "activation",
completedSteps: ["workspace", "configuration", "connectors"],
preferences: { useCase, industry, department, companySize, goal, workspaceName, workspaceType },
});
- Initialize Spine:
await initializeSpine({
domain: resolvedDomain,
industry: data.industry,
department: data.department,
connectors: [],
});
- Update User Profile:
await updateUser({
onboarding_complete: true,
domain: resolvedDomain,
department: data.department,
useCase: data.useCase,
userName: workspaceName,
});
- Complete Onboarding:
await completeOnboarding({
preferences: {
/* all onboarding data */
},
});
- Create Free Subscription:
await apiFetch("/api/v1/subscriptions", {
method: "POST",
body: { tenantId, planId: "free" },
});
Step 4: Completion
Route: /onboarding/complete
Component: CompletionScreen
Behavior:
- Shows success message with checkmark
- Auto-redirects to workbench after 3 seconds
- Two manual options:
- Browse Marketplace - Go to connector marketplace
- Go to Workbench Now - Immediate redirect
Marketplace Intent Handling:
- If user came from marketplace connector activation
- Shows "Connect [Connector Name]" button
- Redirects to
/marketplace?activate=[connector-id]
Auto-redirect:
setTimeout(() => {
navigate("/app", { replace: true });
}, 2000);
Backend Onboarding Service
Gateway Onboarding (services/gateway/src/onboarding.ts)
Key Functions:
getOrCreateUser
// Called after OAuth callback
// - Checks if user exists in tenant
// - Creates new user if needed
// - Returns OnboardingContext with isNewUser flag
getAvailableRoles
// Returns 10 predefined roles:
// - sales_rep, sales_manager
// - cs_manager, cs_specialist
// - finance_manager, support_lead
// - engineering_lead, marketing_manager
// - ops_manager, ceo
// Each with: suggestedConnectors, defaultDomain, defaultView
getAvailableConnectors
// Returns 15+ connectors filtered by subscription tier:
// - CRM: Salesforce, Freshsales, HubSpot
// - Enrichment: Apollo
// - Accounting: Stripe, Razorpay, QuickBooks
// - Communications: Zendesk, Intercom, Gmail, Slack, Zoom
// - Analytics: GitHub, Jira, Google Analytics
// Tiers: free, starter, pro, enterprise
completeOnboarding
// Finalizes onboarding:
// - Updates user role in users table
// - Stores connector selections in tenant_spine_config
// - Logs onboarding event in audit_log
// - Marks onboarding_completed_at timestamp
Workspace API Endpoints
/api/v1/workspace/initialize-spine
Method: POST
Purpose: Initialize Spine schema for tenant
Request:
{
domain: "CUSTOMER_SUCCESS" | "SALES" | "REVOPS" | ...,
industry?: string,
department?: string,
connectors: Array<{
provider: string,
flowType: "A" | "B" | "C"
}>
}
Response:
{
tenantConfig: {
id: string,
domain: string,
connectors: Record<string, any>
},
syncJobs: Array<{
jobId: string,
connector: string,
status: string
}>
}
/api/v1/workspace/onboarding-state
Methods: GET, PATCH
Purpose: Manage onboarding session state
GET Response:
{
onboarding: {
status: "not_started" | "in_progress" | "completed",
currentStep: string,
completedSteps: string[],
connectorsConfig?: Array<{...}>,
creamyJobId?: string,
normalizerJobId?: string,
preferences?: Record<string, unknown>,
entry?: { source: "direct" | "marketplace" | "mcp" }
}
}
PATCH Request:
{
currentStep?: "welcome" | "workspace" | "configuration" | "connectors" | "activation" | "complete",
completedSteps?: string[],
preferences?: Record<string, unknown>
}
/api/v1/workspace/complete-onboarding
Method: POST
Purpose: Finalize onboarding and trigger background jobs
Request:
{
preferences?: Record<string, any>
}
Response:
{
success: boolean,
redirectUrl: string,
backgroundJobs: Array<{
jobId: string,
type: string,
status: string
}>
}
/api/v1/workspace/progress
Method: GET
Purpose: Poll sync job progress during onboarding
Response:
{
type: "sync_progress",
jobs: Array<{
jobId: string,
connector: string,
phase: "creamy" | "needed" | "delta",
status: "pending" | "running" | "completed" | "failed",
progress: {
total?: number,
processed?: number,
percentage?: number,
stage?: string
}
}>
}
Onboarding Intent System
Purpose: Carry entry point through hosted authentication without putting connector identity in OAuth URL
File: apps/web/src/lib/onboarding-intent.ts
Intent Types:
type OnboardingIntent =
| { version: 1; source: "direct" }
| {
version: 1;
source: "marketplace";
connector: { id: string; name: string; authType: "oauth" | "api_key" };
};
Functions:
getOnboardingIntent()- Read from sessionStorageensureDirectOnboardingIntent()- Set direct intent if none existssetMarketplaceConnectorIntent()- Set marketplace connector intentclearOnboardingIntent()- Clear after onboarding complete
Storage: SessionStorage (navigation convenience, not source of truth)
Domain Resolution Logic
File: apps/web/src/OnboardingShell.tsx
Mapping Function:
function resolveDomain(useCase: string, department: string): string;
Domain Mappings:
| Use Case | Department | Domain |
|---|---|---|
| personal | any | PERSONAL |
| work | SALES | SALES |
| work | MARKETING | MARKETING |
| work | REVOPS | REVOPS |
| work | CUSTOMER_SUCCESS | CUSTOMER_SUCCESS |
| work | ENGINEERING/PRODUCT/IT | PRODUCT_ENGINEERING |
| work | OPERATIONS | CUSTOMER_SUCCESS |
| work | SUPPLY_CHAIN | PROCUREMENT |
| work | SERVICE_OPS | SERVICE |
| work | PROJECT_MANAGEMENT | CUSTOMER_SUCCESS |
| work | FINANCE | FINANCE |
| work | LEGAL/HR | CUSTOMER_SUCCESS |
| business | (same as work) | (same as work) |
Fallback: If no match, defaults to CUSTOMER_SUCCESS (business) or PERSONAL (personal)
Draft Persistence
Storage Key: iw_onboarding_draft_{userId}
Storage: SessionStorage
Persisted Data:
{
version: 1,
currentPath: string,
data: {
useCase?: string,
industry?: string,
department?: string,
companySize?: string,
goal?: string,
workspaceName?: string,
workspaceType?: string
},
updatedAt: number
}
Behavior:
- Auto-saves on each step completion
- Restores on page reload
- Cleared after successful onboarding completion
Step Indicator
Visual Progress: 4 dots with connecting lines
●──●──●──●
Step 1 of 4
Steps:
- Welcome (
/onboarding) - Profile (
/onboarding/profile) - Workspace (
/onboarding/workspace) - Done (
/onboarding/complete)
Current Step Highlighting: Primary color for completed and current steps
Animation & Transitions
Library: Framer Motion
Transitions:
- Fade in/out between steps
- Slide up/down for step changes
- Scale effects on button interactions
- Pulse animation for spine initialization indicator
Loading States:
- Spinner during async operations
- Disabled button states during submission
- Progress indicators for background jobs
Error Handling
Frontend:
- Try-catch around all async operations
- Console error logging with context
- Graceful degradation (continue on failure)
- User-friendly error messages
Backend:
- Database transaction rollback on failure
- Audit logging for all onboarding events
- Idempotency for retry scenarios
- Tenant isolation enforcement
Post-Onboarding Flow
Immediate Actions:
- Clear sessionStorage draft
- Clear onboarding intent
- Redirect to workbench or marketplace
Workbench Entry:
- User sees role-specific modules
- Spine projection based on domain
- Empty state with "Get Started" prompts
- Suggested connectors based on role
Marketplace Entry (if connector intent):
- Pre-selected connector from intent
- OAuth flow initiation
- Connector activation wizard
Subscription Creation
Default Plan: Free tier
API Call:
POST /api/v1/subscriptions
{
tenantId: string,
planId: "free"
}
Behavior:
- Best-effort (failure doesn't block onboarding)
- Console error logging
- Can be completed later in settings
Architecture Compliance
Frozen Architecture Alignment:
✅ Product = Three Concepts Only
- Onboarding (initial setup)
- User Workbench (role-specific projection)
- Silent Twin (contextual assistance)
✅ Spine is SSOT
- Onboarding configures Spine schema
- Spine owns all operational truth
- Memory informs truth, not vice versa
✅ Governance is Hard Gate
- No connector activation without approval
- OAuth flows properly gated
- Tenant isolation enforced
✅ Workbench is One Surface
- No L1/L2/L4/L7 in onboarding UI
- Single progressive flow
- Role projection configured, not layered
✅ Twin is Silent by Default
- Twin not involved in onboarding
- No AI assistance during setup
- User-driven configuration only
Key Files Reference
| File | Purpose |
|---|---|
apps/web/src/OnboardingShell.tsx | Main onboarding shell with 4-step flow |
apps/web/src/components/activation/onboarding/steps/WelcomeStep.tsx | Step 1: Use case selection |
apps/web/src/components/activation/onboarding/steps/ProfileStep.tsx | Step 2: Industry/department selection |
apps/web/src/components/activation/onboarding/steps/GoalsStep.tsx | Step 3: Goals and workspace creation |
apps/web/src/api/workspace.ts | Workspace API client (initialize-spine, onboarding-state, complete-onboarding) |
apps/web/src/lib/onboarding-intent.ts | Onboarding intent management (direct vs marketplace) |
services/gateway/src/onboarding.ts | Backend onboarding service (roles, connectors, user creation) |
services/gateway/src/index.ts | Gateway routing for onboarding endpoints |
Summary
The IntegrateWise onboarding flow is a 4-step progressive wizard that:
- Captures user intent (personal/work/business use case)
- Configures the Spine (industry + department → domain resolution)
- Creates the workspace (goals + workspace name + type)
- Initializes Spine schema and redirects to workbench or marketplace
The flow is entry-point agnostic - works equally well for direct sign-up and marketplace connector activation. It uses session storage for draft persistence, backend session for state management, and Clerk OAuth for authentication.
Key architectural principles maintained:
- Single Workbench surface (no layer complexity)
- Spine as single source of truth
- Role-based domain projection
- Governance gates for connector activation
- Silent Twin (no AI during onboarding)