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)
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).Submit
AuthProvider.signUp() calls supabase.auth.signUp() directly — passing email, password, and user_metadata (username, first_name, surname). No web API route involved.Screens & Components
| Platform | Screen | Components |
|---|---|---|
| Mobile | app/register.tsx | Form fields, validation display, useUsernameCheck for real-time availability |
| Mobile | app/register-success.tsx | Success confirmation |
| Web Interim | /confirmation-success | Email verified success page (after clicking confirmation link) |
How It Works
The mobileAuthProvider.signUp() calls supabase.auth.signUp() directly — no web API route involved. It passes:
emailandpasswordfor authenticationuser_metadatacontainingusername,first_name,surname
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
| Table | Operation | Details |
|---|---|---|
auth.users | INSERT | Created by Supabase Admin Auth. Stores email, encrypted_password, raw_user_meta_data (username, first_name, surname) |
profiles | INSERT | Created 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
profileswithid = NEW.id, extractsusername,first_name,surnamefromraw_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_availableRPC withp_usernameand optionalp_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)
| Field | Constraint |
|---|---|
username | Required, string |
firstName | Required, string |
surname | Required, string |
email | Required, valid email format |
password | Required, minimum length |
Loops.so Integration
- On successful registration,
AuthProvider.signUp()callsregisterUserMarketing()(non-blocking, parallel) - Sends email, firstName, surname, and userId to Loops.so via
marketing-eventsedge 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)