| Route | Purpose | Auth Required |
|---|
/sign-in | User login | No (redirects to / if authenticated) |
/sign-up | New account creation | No (redirects to / if authenticated) |
/forgot-password | Password reset request | No |
/waiting-for-approve | Registration gate (private beta) | Yes |
- Email/Password - Form-based registration
- Google OAuth - One-click via
signInWithGoogle()
| Field | Type | Required | Validation |
|---|
firstName | text | Yes | Min 1 character |
lastName | text | Yes | Min 1 character |
email | email | Yes | Valid email format |
password | password | Yes | Min 8 characters |
agreeToTerms | checkbox | Yes | Must be true |
- URL:
https://app.termly.io/policy-viewer/policy.html?policyUUID=0e8bd91c-0128-4955-8f7e-e17b7f697a2a
- Opens in new tab
- Must be accepted to register
- Firebase Auth account created
- Display name set as
${firstName} ${lastName}
- User document created at
users/{uid}
- Referral signup processed (from cookie, silent failure)
- Analytics events fired
- Redirect to
/
- Toast: “Account created successfully”
New user = (Date.now() - creationTime) < 5000ms
If new user detected via Google, referral tracking and sign_up event also fire.
| Event | When | Key Data |
|---|
sign_up | Successful registration | method, user_id, email_domain, display_name |
sign_up_failed | Registration error | method, error_type |
form_interaction | Field focus/blur/change | form_name, field_name, interaction_type |
| User properties set | On signup | user_type=new, signup_method, account_created_date |
| Field | Type | Required | Validation |
|---|
email | email | Yes | Valid email format |
password | password | Yes | Min 8 characters |
- Success: Toast “Signed in successfully”, redirect to
/
- Failure: Toast with Firebase error message
- Forgot password link: Navigates to
/forgot-password
| Event | Key Data |
|---|
sign_in_attempt | method, page_location |
sign_in | method, user_id, is_new_user, email_domain |
sign_in_failed | method, error_type, error_message |
- User navigates to
/forgot-password
- Enters email address (required, valid format)
- Clicks “Send Email”
- Firebase Auth sends password reset email
- Toast: “Password reset email sent”
- Redirect to
/sign-in
The actual password reset is handled by Firebase Auth’s native flow (not within the app).
Route: /waiting-for-approve
First 5 seconds: Loading animation with “Checking Account Status”
After loading:
- “We’re in Private Beta” headline with badge
- Two options:
- Have a Referral Code - Input field + “Link” button
- Join the Waitlist - Informational message
- User enters referral code (or code auto-detected from cookie)
- System validates code exists at
referralCodes/{code} in Firestore
- If invalid: toast error “Invalid referral code”
- If valid:
- Checks for duplicate at
referrals/{code}_{userId}
- Creates referral document at
referrals/{code}_{userId}
- Checks user registry limits at
config/userRegistry
- Auto-approval logic:
if (registry.enabled && registry.countCurrent < registry.limitUsers) {
approve user, increment countCurrent
| Field | Value |
|---|
registrationApproved | true |
waitingForApproval | false |
isReferred | true |
referralId | referral document ID |
referralCode | code used |
updatedAt | Timestamp.now() |
Path: referrals/{code}_{userId}
| Field | Value |
|---|
referralCode | code entered |
referrerId | code owner’s UID |
refereeId | current user’s UID |
status | converted |
conversionEvent | signup |
metadata.signUpSource | waiting-for-approve |
metadata.signUpMethod | referral |
- Toast: “Referral code linked successfully! Redirecting…”
- 2-second delay, then redirect to
/
AuthGuard (requireAuth=true)
├── if route === "waiting-for-approve" → render directly
├── CustomGuard #1: checkRegistrationApproved()
│ ├── FALSE → redirect to /waiting-for-approve
└── CustomGuard #2: checkOnboardingCompleted()
├── FALSE → redirect to /onboarding
checkRegistrationApproved() checks users/{uid}.registrationApproved === true
checkOnboardingCompleted() checks users/{uid}.onboardingCompleted === true
- Both use server-side reads (
getFromServer()) for latest data
On app load, cookieManager.initializeReferralTracking() runs:
- Extracts
referralCode from URL query params
- Extracts UTM parameters (
utm_source, utm_medium, utm_campaign, utm_term, utm_content)
- Saves to cookies with 90-day expiration (path
/, SameSite Lax)
- Cleans tracking params from browser URL
| Cookie | Content | Expiration |
|---|
referralCode | Referral code string | 90 days |
referralData | JSON: {code, timestamp, source, utmParams} | 90 days |
users/{uid} - User document with email, displayName, email metadata
users/{uid} - Updated with registrationApproved, referral fields
referrals/{code}_{uid} - Referral transaction record
config/userRegistry - countCurrent incremented
- Analytics properties and events only (no Firestore writes)