<<<<<<< HEAD
A full-stack Next.js 16 web app for student clubs to manage season-based badges, member requests, profiles, and a leaderboard.
A full-stack Next.js 14 web app for student clubs to manage season-based badges, member requests, profiles, and a leaderboard.
Stack: Next.js 14 · Firebase (Firestore + Auth) · NextAuth.js · Tailwind CSS · TypeScript · Vercel
4c7b7cf (resolve conflict)
| Feature | Description |
|---|---|
| Google Login | Members sign in with their Google account via NextAuth |
| Season Badges | Admins create badge sets per season with custom points |
| Badge Requests | Members submit requests with proof; admins approve/reject |
| Member Profiles | Earned badges grouped by season + request history |
| Leaderboard | Members ranked by total points with a podium for top 3 |
| Admin Panel | Dashboard, request review, season & badge management |
| Role Protection | Middleware blocks non-admins from admin routes |
git clone https://github.com/YOUR_USERNAME/club-badge-system
cd club-badge-system
npm install- Go to Firebase Console → Create a project
- Enable Firestore Database (start in production mode)
- Enable Authentication → Sign-in method → Google → Enable it
- Go to Project Settings → General → scroll to "Your apps" → Add web app
- Copy the
firebaseConfigvalues — you'll need them for.env.local - Go to Project Settings → Service Accounts → Generate new private key
- Download the JSON file — you'll need
project_id,client_email, andprivate_key
- Go to Google Cloud Console
- Select your Firebase project → APIs & Services → Credentials
- Create Credentials → OAuth 2.0 Client ID → Web application
- Add Authorized redirect URIs:
http://localhost:3000/api/auth/callback/google(local)https://YOUR_APP.vercel.app/api/auth/callback/google(production)
- Copy the Client ID and Client Secret
cp .env.example .env.localFill in all values in .env.local:
# Firebase Client SDK
NEXT_PUBLIC_FIREBASE_API_KEY=...
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your-project.firebaseapp.com
NEXT_PUBLIC_FIREBASE_PROJECT_ID=your-project-id
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=your-project.appspot.com
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=...
NEXT_PUBLIC_FIREBASE_APP_ID=...
# Firebase Admin SDK
FIREBASE_ADMIN_PROJECT_ID=your-project-id
FIREBASE_ADMIN_CLIENT_EMAIL=firebase-adminsdk-xxxx@your-project.iam.gserviceaccount.com
FIREBASE_ADMIN_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nYOUR KEY\n-----END PRIVATE KEY-----\n"
# NextAuth
NEXTAUTH_SECRET=run `openssl rand -base64 32` to generate this
NEXTAUTH_URL=http://localhost:3000
# Google OAuth
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...In Firebase Console → Firestore → Rules, paste:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Anyone can read users and leaderboard
match /users/{uid} {
allow read: if true;
allow write: if request.auth != null && request.auth.uid == uid;
// Earned badges sub-collection
match /earnedBadges/{badgeId} {
allow read: if true;
allow write: if false; // only server (admin SDK) writes
}
}
// Seasons and badges are public read
match /seasons/{id} {
allow read: if true;
allow write: if false; // server only
}
match /badges/{id} {
allow read: if true;
allow write: if false; // server only
}
// Badge requests
match /badgeRequests/{id} {
allow read: if request.auth != null;
allow create: if request.auth != null;
allow update: if false; // server only
}
}
}
npm run dev<<<<<<< HEAD
After signing in for the first time:
- Go to Firebase Console → Firestore →
userscollection - Find your user document (it was created automatically on first login)
- Change the
rolefield from"member"to"admin" - Refresh the site — you'll now see the
~/adminlink in the navbar
npm install -g vercel
vercel login
vercel- Push your code to a GitHub repository
- Go to vercel.com → New Project → Import your repo
- Framework: Next.js (auto-detected)
- Add all environment variables from
.env.localin the Vercel dashboard - For
NEXTAUTH_URL, set it tohttps://YOUR_APP.vercel.app - For
FIREBASE_ADMIN_PRIVATE_KEY, paste the full key including\ncharacters - Click Deploy
- Go back to Google Cloud Console → OAuth credentials → add your Vercel URL to Authorized redirect URIs:
https://YOUR_APP.vercel.app/api/auth/callback/google - Go to Firebase Console → Authentication → Authorized domains → add your Vercel domain
club-badge-system/
├── app/
│ ├── page.tsx # Home / landing
│ ├── login/page.tsx # Google sign-in
│ ├── badges/
│ │ ├── page.tsx # Browse season badges
│ │ └── [id]/request/page.tsx # Submit badge request
│ ├── leaderboard/page.tsx # Ranked members
│ ├── profile/[uid]/page.tsx # Member profile
│ ├── admin/
│ │ ├── page.tsx # Admin dashboard
│ │ ├── requests/page.tsx # Approve / reject
│ │ └── seasons/page.tsx # Create seasons & badges
│ └── api/
│ ├── auth/[...nextauth]/ # NextAuth handler
│ ├── badges/route.ts # Badge CRUD
│ ├── requests/
│ │ ├── route.ts # Submit / list requests
│ │ └── [id]/route.ts # Approve / reject
│ └── admin/seasons/route.ts # Season management
├── components/
│ ├── layout/Navbar.tsx # Top nav
│ └── ui/index.tsx # Shared components
├── lib/
│ ├── firebase.ts # Client SDK
│ ├── firebase-admin.ts # Admin SDK (server only)
│ ├── auth.ts # NextAuth config
│ └── db.ts # Firestore helpers
├── types/
│ ├── index.ts # All TypeScript types
│ └── next-auth.d.ts # Session augmentation
├── middleware.ts # Route protection
├── .env.example # Env var template
└── vercel.json # Vercel config
- Start a season → Admin panel → Seasons → Create "Spring 2025" → Set active
- Add badges → Select the season → Fill in name, icon, description, points, category
- Members sign in → Browse badges → Submit requests with proof
- Admins review → Admin panel → Requests → Approve or Reject (with optional note)
- Points update automatically → Leaderboard re-ranks instantly
| What to change | Where |
|---|---|
| Club name / branding | app/layout.tsx, components/layout/Navbar.tsx |
| Color theme | tailwind.config.js and app/globals.css |
| Badge categories | types/index.ts → BadgeCategory + app/badges/page.tsx |
| Leaderboard size | app/leaderboard/page.tsx → change limit(50) |
| Admin emails | Manually set role: "admin" in Firestore |
=======
After signing in for the first time:
- Go to Firebase Console → Firestore →
userscollection - Find your user document (it was created automatically on first login)
- Change the
rolefield from"member"to"admin" - Refresh the site — you'll now see the
~/adminlink in the navbar
npm install -g vercel
vercel login
vercel- Push your code to a GitHub repository
- Go to vercel.com → New Project → Import your repo
- Framework: Next.js (auto-detected)
- Add all environment variables from
.env.localin the Vercel dashboard - For
NEXTAUTH_URL, set it tohttps://YOUR_APP.vercel.app - For
FIREBASE_ADMIN_PRIVATE_KEY, paste the full key including\ncharacters - Click Deploy
- Go back to Google Cloud Console → OAuth credentials → add your Vercel URL to Authorized redirect URIs:
https://YOUR_APP.vercel.app/api/auth/callback/google - Go to Firebase Console → Authentication → Authorized domains → add your Vercel domain
club-badge-system/
├── app/
│ ├── page.tsx # Home / landing
│ ├── login/page.tsx # Google sign-in
│ ├── badges/
│ │ ├── page.tsx # Browse season badges
│ │ └── [id]/request/page.tsx # Submit badge request
│ ├── leaderboard/page.tsx # Ranked members
│ ├── profile/[uid]/page.tsx # Member profile
│ ├── admin/
│ │ ├── page.tsx # Admin dashboard
│ │ ├── requests/page.tsx # Approve / reject
│ │ └── seasons/page.tsx # Create seasons & badges
│ └── api/
│ ├── auth/[...nextauth]/ # NextAuth handler
│ ├── badges/route.ts # Badge CRUD
│ ├── requests/
│ │ ├── route.ts # Submit / list requests
│ │ └── [id]/route.ts # Approve / reject
│ └── admin/seasons/route.ts # Season management
├── components/
│ ├── layout/Navbar.tsx # Top nav
│ └── ui/index.tsx # Shared components
├── lib/
│ ├── firebase.ts # Client SDK
│ ├── firebase-admin.ts # Admin SDK (server only)
│ ├── auth.ts # NextAuth config
│ └── db.ts # Firestore helpers
├── types/
│ ├── index.ts # All TypeScript types
│ └── next-auth.d.ts # Session augmentation
├── middleware.ts # Route protection
├── .env.example # Env var template
└── vercel.json # Vercel config
- Start a season → Admin panel → Seasons → Create "Spring 2025" → Set active
- Add badges → Select the season → Fill in name, icon, description, points, category
- Members sign in → Browse badges → Submit requests with proof
- Admins review → Admin panel → Requests → Approve or Reject (with optional note)
- Points update automatically → Leaderboard re-ranks instantly
| What to change | Where |
|---|---|
| Club name / branding | app/layout.tsx, components/layout/Navbar.tsx |
| Color theme | tailwind.config.js and app/globals.css |
| Badge categories | types/index.ts → BadgeCategory + app/badges/page.tsx |
| Leaderboard size | app/leaderboard/page.tsx → change limit(50) |
| Admin emails | Manually set role: "admin" in Firestore |
4c7b7cf (resolve conflict)