Referral System
Every user has a unique 6-character referral code (e.g. K7MX2Q). When a new user signs up using someone's code, the referrer earns +5 bonus credits.
How it works — step by step
1. Every user gets a code
When a user's Firestore document is created (new sign-up), a referral code is generated and stored on their doc:
users/{uid}
referralCode: "K7MX2Q"
referralsMade: 0Existing users who signed up before this feature existed also get a code — it is automatically generated and saved the next time they open the app, inside the onAuthStateChanged handler in AuthProvider.tsx.
Code generation lives in components/providers/AuthProvider.tsx → generateReferralCode(uid). It builds a 6-character uppercase alphanumeric string (no ambiguous chars like O, 0, I, 1) from the user's uid + current timestamp.
2. New user enters the code on the login page
On app/(auth)/login/page.tsx there is an optional "Referral code" input above the Sign In button. The user types the code they received from a friend.
When they tap Sign in with Google, the code is saved to localStorage under the key referral_code before the Google auth flow starts.
3. After sign-in, the code is redeemed
In AuthProvider.tsx, after Google sign-in completes, saveUserToFirestore is called. It returns true if this is a brand-new user.
If true, the code is read from localStorage and sent to the server:
POST /api/redeem-referral
{ newUserId: "...", referralCode: "K7MX2Q" }The localStorage entry is then deleted so it cannot be redeemed again on a future login.
4. Server validates and awards credits
The API route app/api/redeem-referral/route.ts does all validation server-side (using Firebase Admin SDK so it cannot be cheated from the client):
| Check | What happens if it fails |
|---|---|
referralCode exists in Firestore | Returns 404 — invalid code |
| Referrer is not the same person as the new user | Returns 400 — cannot refer yourself |
New user doesn't already have a referredBy field | Returns 400 — already redeemed |
If all checks pass:
- +5 credits are added to the referrer's
users/{referrerId}/settings/creditsdoc referredBy: referrerIdis written to the new user's doc (prevents double-redeem)referralsMadecounter on the referrer is incremented by 1
5. User shares their own code from the Profile page
On app/(dashboard)/profile/page.tsx there is a "Your Referral Code" card that:
- Reads
referralCodefrom the user's Firestore doc - Displays it in a large, spaced-out format
- Has a copy-to-clipboard button (shows a ✓ checkmark for 2 seconds after copying)
Files involved
| File | Role |
|---|---|
components/providers/AuthProvider.tsx | Generates codes, backfills existing users, calls redeem after new sign-up |
app/api/redeem-referral/route.ts | Server-side validation + credit award |
app/(auth)/login/page.tsx | Referral code input field, saves to localStorage |
app/(dashboard)/profile/page.tsx | Shows the user's own code with copy button |
Anti-abuse rules
- Redemption is server-side only — the client cannot award itself credits
- A user cannot use their own referral code
- Each new user can only redeem one referral code (enforced by the
referredByfield) - The localStorage entry is cleared immediately after the first redeem attempt, so refreshing or re-logging does not trigger a second call

