Technical docs

Onboarding

Overview

Current bootstrap and invite-entry behavior for new users.

Self-serve bootstrap

  • Trigger:
  • Google OAuth callback at `/api/auth/google/callback`
  • runs only for a brand-new user when there is no invite code in OAuth `state`
  • Backend builder:
  • `OrganizationBuilder.createDefaultOrganization()`
  • creates `My Organization`
  • seeds `available_tokens` with `DEFAULT_AVAILABLE_TOKENS` (`2000`)
  • sets the new org as the user's `current_organization_id`

Optional default AI teammate

  • Builder reads system setting `onboarding_employee_id`.
  • If the setting points to a valid system AI teammate, that teammate is cloned into the new org.

Ally welcome bootstrap

  • The builder resolves the new user's personal Ally employee in the new org with `AiEmployeeService.findUserAllyEmployee(organizationId, user.id)`.
  • If that personal Ally employee exists, the backend:
  • creates or restores the user's employee-chat-backed Ally conversation for the new org
  • inserts a completed AI welcome message
  • updates the conversation last-message summary so it appears immediately in history
  • The current seeded welcome starts with `Welcome — I’m Ally.`.

First redirect after signup

  • `getOnboardingRedirectUrl(organizationId)` currently returns:
  • `/staff?onboarding=true`
  • The current onboarding redirect no longer targets a first-AI-teammate detail route.
  • If organization ID is missing, the fallback is `/`.

Frontend onboarding behavior

  • `ViewModeManager` watches `?onboarding=true`.
  • After scoped internal-chat state is restored for the current `userId + organizationId`, it auto-opens Ally if Ally is not already visible.
  • The onboarding open path forces Ally into a floating window near the bottom-right corner:
  • margin: `20px`
  • width: `MIN_WINDOW_SIZE.width`
  • height: `60%` of viewport height
  • On mobile, floating chat is converted back into the docked panel.

Invite route (`/invite/[code]`)

  • Page bootstrap:
  • loads invite metadata from `GET /api/invites/{code}`
  • shows one of:
  • guest invite view
  • authenticated accept view
  • already-in-organization view
  • not-found state
  • Guest behavior:
  • `Sign in with Google` starts OAuth with `state: { inviteCode: code }`
  • the guest view warns that sign-in will automatically accept the invite
  • OAuth callback behavior with an invite code:
  • backend tries `AcceptInviteProcessor` immediately
  • on success, callback returns redirect `/`
  • on handled invite failure, callback redirects back to `/invite/{code}`
  • Authenticated behavior on the invite page:
  • `Accept Invite` calls `GET /api/invites/{code}/accept`
  • accepted invites redirect to `/`
  • `already_in_organization` shows `Go to Dashboard`

Support notes

  • Landing on `/` after self-serve signup usually means the onboarding redirect did not receive an organization ID.
  • Missing Ally welcome usually means the user's personal Ally employee was not created or could not be resolved in the new org.
  • If `?onboarding=true` is present and Ally does not auto-open after load, treat that as unexpected.
  • Invite acceptance always switches the user's current organization to the invited org.

Start building your AI team