Skip to main content

What It Does

New user account creation with email/password authentication, real-time username availability checking, and automatic profile provisioning via database trigger.

User Flow (Mobile)

1

Navigate to Register

User taps “Register” on the login screen → navigates to app/register.tsx
2

Fill in Details

Username, first name, surname, email, password. Client-side Zod validation via registerSchema from the shared package. Username availability checked in real-time via useUsernameCheck hook (debounced 300ms, calls check_username_available RPC).
3

Submit

AuthProvider.signUp() calls supabase.auth.signUp() directly — passing email, password, and user_metadata (username, first_name, surname). No web API route involved.
4

Confirmation

On success → navigates to app/register-success.tsx. User receives confirmation email.
5

Email Verification

User clicks confirmation link → web interim /auth/confirm route verifies the OTP token server-side → redirects to /confirmation-success success page.

Screens & Components

PlatformScreenComponents
Mobileapp/register.tsxForm fields, validation display, useUsernameCheck for real-time availability
Mobileapp/register-success.tsxSuccess confirmation
Web Interim/confirmation-successEmail verified success page (after clicking confirmation link)

How It Works

The mobile AuthProvider.signUp() calls supabase.auth.signUp() directly — no web API route involved. It passes:
  • email and password for authentication
  • user_metadata containing username, first_name, surname
On success, the handle_new_user trigger fires automatically to create the profile row. The AuthProvider also calls registerUserMarketing() (non-blocking) to enroll the user in Loops.so for email campaigns via the marketing-events edge function.
The POST /api/auth/register route exists in apps/web for the Phase 2 web client (which uses supabase.auth.admin.createUser() server-side). The mobile app does NOT use this route — it calls supabase.auth.signUp() directly via the Supabase client SDK.

Database

TableOperationDetails
auth.usersINSERTCreated by Supabase Admin Auth. Stores email, encrypted_password, raw_user_meta_data (username, first_name, surname)
profilesINSERTCreated automatically by handle_new_user trigger

Trigger: on_auth_user_created

  • Fires: AFTER INSERT ON auth.users
  • Executes: handle_new_user() (SECURITY DEFINER)
  • Logic: Inserts into profiles with id = NEW.id, extracts username, first_name, surname from raw_user_meta_data. Falls back to 'user_' || substr(NEW.id, 1, 8) if username is missing.
  • Defaults: location = '', bio = '', all counters default to 0.

Username Availability Check

useUsernameCheck hook (src/hooks/useUsernameCheck.ts):
  • Debounced (300ms) username availability checking
  • Calls check_username_available RPC with p_username and optional p_exclude_user_id
  • Returns availability status with visual feedback (green check / red X)
  • Used in both registration form and profile edit (settings) screen

Validation (registerSchema)

FieldConstraint
usernameRequired, string
firstNameRequired, string
surnameRequired, string
emailRequired, valid email format
passwordRequired, minimum length

Loops.so Integration

  • On successful registration, AuthProvider.signUp() calls registerUserMarketing() (non-blocking, parallel)
  • Sends email, firstName, surname, and userId to Loops.so via marketing-events edge function
  • On account deletion, removeUserMarketing() removes them via the same edge function
  • The Loops API key is stored as a Supabase edge function secret (not in client env)