packages/features/ee/organizations/lib/service/onboarding/OrganizationOnboardingSetup.md
This document explains how the organization onboarding system works and how to configure it for different deployment scenarios.
The organization onboarding system supports two different flows:
The system automatically selects the appropriate flow based on environment variables and user permissions.
The OrganizationOnboardingFactory class determines which onboarding service to use:
OrganizationOnboardingFactory.create(user)
→ BillingEnabledOrgOnboardingService | SelfHostedOrganizationOnboardingService
The factory uses the following logic to determine which service to instantiate:
IF process.env.NEXT_PUBLIC_IS_E2E is set:
→ Use SelfHostedOrganizationOnboardingService (E2E tests always skip billing)
ELSE IF IS_TEAM_BILLING_ENABLED is true:
→ Use BillingEnabledOrgOnboardingService (hosted environment with Stripe)
ELSE IF user.role is ADMIN:
→ Use SelfHostedOrganizationOnboardingService (self-hosted admins skip billing)
ELSE:
→ Use BillingEnabledOrgOnboardingService (non-admins need billing even on self-hosted)
# Stripe Configuration
STRIPE_CLIENT_ID=your_stripe_client_id
NEXT_PUBLIC_STRIPE_PUBLIC_KEY=your_stripe_public_key
STRIPE_PRIVATE_KEY=your_stripe_private_key
# These enable IS_STRIPE_ENABLED and IS_TEAM_BILLING_ENABLED
# Force hosted features on self-hosted instances
NEXT_PUBLIC_HOSTED_CAL_FEATURES=true
# E2E testing (disables billing flow)
NEXT_PUBLIC_IS_E2E=1
# Organization pricing
NEXT_PUBLIC_ORGANIZATIONS_SELF_SERVE_PRICE_NEW=37
The system relies on several computed constants from @calcom/lib/constants:
IS_TEAM_BILLING_ENABLED: IS_STRIPE_ENABLED && HOSTED_CAL_FEATURES
OrganizationOnboardingFactoryIS_STRIPE_ENABLED: !!(STRIPE_CLIENT_ID && NEXT_PUBLIC_STRIPE_PUBLIC_KEY && STRIPE_PRIVATE_KEY)
HOSTED_CAL_FEATURES: process.env.NEXT_PUBLIC_HOSTED_CAL_FEATURES || !IS_SELF_HOSTED
IS_SELF_HOSTED: !CAL_DOMAINS.some(domain => WEBAPP_HOSTNAME.endsWith(domain))
IS_TEAM_BILLING_ENABLED_CLIENT: !!process.env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY && HOSTED_CAL_FEATURES
onboardingStore.tsEnvironment:
# Domain: *.cal.com, *.cal.dev, etc.
STRIPE_CLIENT_ID=ca_xxx
NEXT_PUBLIC_STRIPE_PUBLIC_KEY=pk_live_xxx
STRIPE_PRIVATE_KEY=sk_live_xxx
Result:
IS_SELF_HOSTED = falseHOSTED_CAL_FEATURES = trueIS_TEAM_BILLING_ENABLED = trueEnvironment:
# Domain: custom.example.com
NEXT_PUBLIC_HOSTED_CAL_FEATURES=true
STRIPE_CLIENT_ID=ca_xxx
NEXT_PUBLIC_STRIPE_PUBLIC_KEY=pk_live_xxx
STRIPE_PRIVATE_KEY=sk_live_xxx
Result:
IS_SELF_HOSTED = trueHOSTED_CAL_FEATURES = true (forced)IS_TEAM_BILLING_ENABLED = trueEnvironment:
# Domain: custom.example.com
# No Stripe configuration
Result:
IS_SELF_HOSTED = trueHOSTED_CAL_FEATURES = falseIS_TEAM_BILLING_ENABLED = falseRecommendation: In this scenario, only admins should be allowed to create organizations.
Environment:
NEXT_PUBLIC_IS_E2E=1
# Any other configuration
Result:
The system differentiates between two user roles:
UserPermissionRole.ADMIN)IS_TEAM_BILLING_ENABLED is falseUserPermissionRole.USER)