Features
PreviousNext

Onboarding

Configure and extend the mobile onboarding flow with schema, step config, and filters.

What It Does

apps/mobile uses a QuickForm stepper onboarding flow that runs before the main app stack. The flow is schema-driven and extensible via filters.

When To Use

  • You need to collect user profile data before first app usage.
  • You need app-specific onboarding steps on top of the default flow.
  • You need route-level onboarding extensions (/onboarding/[onboardingPath]).

Prerequisites

  • Authenticated user session.
  • completedOnboarding field available on user record.
  • apps/mobile/config/onboarding.config.tsx configured.

Flow Overview

  • app/(app)/_layout.tsx redirects users with !completedOnboarding to /onboarding.
  • app/onboarding/index.tsx renders the default stepper flow.
  • app/onboarding/[onboardingPath]/index.tsx supports custom onboarding routes from filters.

How To Use

Define schema and default steps.

apps/mobile/config/onboarding.config.tsx
import { z } from 'zod'; export const onboardingSchema = { userImageUrl: z.string().optional().nullable(), userName: z.string().trim().min(1).max(64), userPhone: z.string().trim().max(16).optional().or(z.literal('')), userEmail: z.string().email(), userRole: z.enum(['designer', 'programmer', 'product_manager', 'tester', 'marketer']), }; export const onboardingStepsConfig = [ { type: 'step', label: 'User', settings: [ { type: 'user_media', slug: 'userImageUrl' }, { type: 'text', slug: 'userName', label: 'Name' }, { type: 'text', slug: 'userEmail', label: 'Email', disabled: true }, ], }, { type: 'step', label: 'Profession', settings: [{ type: 'question_select', slug: 'userRole' }], }, ];

Render onboarding using schema/steps filters.

apps/mobile/app/onboarding/index.tsx
import { QuickForm } from '@kit/native-ui/quick-form';
import { applyAsyncFilter, useApplyFilter } from '@kit/utils/filters';
import { onboardingSchema, onboardingStepsConfig } from '~/config/onboarding.config';
 
const schema = useApplyFilter('get_onboarding_schema', onboardingSchema);
const steps = useApplyFilter('get_onboarding_steps_config', onboardingStepsConfig, { clientTrpc });
const extraInputs = useApplyFilter('get_onboarding_extra_inputs', {});
 
<QuickForm config={onboardingConfig} inputs={extraInputs} onSubmit={handleSubmit} />

Update onboarding completion + redirect.

Default submit path in onboarding/index.tsx:

  • calls clientTrpc.updateUser.fetch(data);
  • refetches getUser query;
  • computes redirect via applyAsyncFilter('on_onboarding_submit', '/', ...);
  • pushes final route.

Add new fields and steps safely.

  1. Add Zod field in onboardingSchema.
  2. Add matching input node in onboardingStepsConfig.
  3. Ensure submit handler forwards this field to API mutation.
  4. If needed, register extra input component through get_onboarding_extra_inputs filter.

Advanced Extension Points

FilterPurpose
get_onboarding_schemaExtend base schema without editing package internals.
get_onboarding_steps_configInsert/reorder/remove steps.
get_onboarding_extra_inputsRegister custom QuickForm input components.
on_onboarding_submitCustomize post-submit redirect + side effects.
render_onboarding_pathRender custom route content in /onboarding/[onboardingPath].

Filter API

Mobile onboarding is extended through organization onboarding filters registered from the shared onboarding package layer.

FilterParametersReturnRegistered By (package file)Initialized In (app entrypoint)Environment
get_onboarding_schema{}QuickFormSchemaMapkit/organization/src/shared/filters/use-filters/use-onboarding-filters.tsxapps/mobile/hooks/use-filters.ts (useOrgFilters)client
get_onboarding_steps_config{ clientTrpc: TrpcClientWithQuery<Router<unknown>> }QuickFormStepConfig<QuickFormSchemaMap>[]kit/organization/src/shared/filters/use-filters/use-onboarding-filters.tsxapps/mobile/hooks/use-filters.ts (useOrgFilters)client
get_onboarding_extra_inputs{}SettingsInputsBasekit/organization/src/shared/filters/use-filters/use-onboarding-filters.tsxapps/mobile/hooks/use-filters.ts (useOrgFilters)client
render_onboarding_path{ onboardingPath: string; clientTrpc: TrpcClientWithQuery<Router<unknown>>; queryClient: QueryClient; defaultSchema: QuickFormSchemaMap; defaultSteps: QuickFormStepConfig<QuickFormSchemaMap>[] }null | { config: QuickFormConfig<QuickFormSchemaMap>; inputs: SettingsInputsBase; onSubmit: (data: unknown) => Promise<void> }kit/organization/src/shared/filters/use-filters/use-onboarding-filters.tsxapps/mobile/hooks/use-filters.ts (useOrgFilters)client
on_onboarding_submit{ data: Record<string, unknown>; clientTrpc: TrpcClientWithQuery<Router<unknown>>; queryClient: QueryClient }stringkit/organization/src/shared/filters/use-filters/use-onboarding-filters.tsxapps/mobile/hooks/use-filters.ts (useOrgFilters)client
get_translations{ language: string; namespace: string }Record<string, string> | nullkit/organization/src/native/filters/use-filters/use-translation-filters.tsxapps/mobile/hooks/use-filters.ts (useOrgFilters)client

MCP Context

capability: onboarding_mobile_flow entrypoints: - apps/mobile/config/onboarding.config.tsx - apps/mobile/app/onboarding/index.tsx - apps/mobile/app/onboarding/[onboardingPath]/index.tsx - apps/mobile/app/(app)/_layout.tsx - apps/mobile/hooks/use-filters.ts - apps/mobile/config/i18n.config.ts - kit/organization/src/shared/filters/use-filters/use-onboarding-filters.tsx - kit/organization/src/native/filters/use-filters/use-onboarding-filters.tsx - kit/organization/src/native/filters/use-filters/use-translation-filters.tsx inputs: - onboarding_schema - onboarding_steps - onboarding_filter_overrides outputs: - gated_onboarding_experience constraints: - user fields in steps must exist in schema - completedOnboarding gating must stay consistent with app layout redirect side_effects: - updates user profile fields and onboarding completion status

Agent Recipe

  1. Extend schema and steps in onboarding.config.tsx.
  2. Add custom inputs/logic through onboarding filters instead of hardcoding package internals.
  3. Verify completedOnboarding redirect behavior in (app)/_layout.tsx and onboarding submit path.

Troubleshooting

  • If fields do not render, verify input type is registered in onboarding inputs map/filters.
  • If user always returns to onboarding, verify updateUser mutation persists completion fields and user query refresh occurs.
  • If custom onboarding path shows 404 (Unmatched), verify render_onboarding_path filter returns content.

How is this guide?

Last updated on 3/27/2026