Skip to content

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.

Screenshot: The referral codeThe referral code


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: 0

Existing 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.tsxgenerateReferralCode(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):

CheckWhat happens if it fails
referralCode exists in FirestoreReturns 404 — invalid code
Referrer is not the same person as the new userReturns 400 — cannot refer yourself
New user doesn't already have a referredBy fieldReturns 400 — already redeemed

If all checks pass:

  • +5 credits are added to the referrer's users/{referrerId}/settings/credits doc
  • referredBy: referrerId is written to the new user's doc (prevents double-redeem)
  • referralsMade counter 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 referralCode from 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

FileRole
components/providers/AuthProvider.tsxGenerates codes, backfills existing users, calls redeem after new sign-up
app/api/redeem-referral/route.tsServer-side validation + credit award
app/(auth)/login/page.tsxReferral code input field, saves to localStorage
app/(dashboard)/profile/page.tsxShows 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 referredBy field)
  • The localStorage entry is cleared immediately after the first redeem attempt, so refreshing or re-logging does not trigger a second call

Released under the MIT License.