A complete full-stack platform for hosting official-style online speedcubing competitions with payment integration, WCA-style timer, and global leaderboards.
Authentication System
- Email/Password + Google OAuth via Firebase
- Auto WCA-style ID generation (Format: 2026RAHK1)
- Role-based access (Admin/User)
- Admin email added
Admin Panel (/admin)
- Create competitions with multiple events (17 WCA events)
- FREE or PAID competition types
- Flexible pricing models:
- Flat price (entire competition)
- Per event pricing
- Base + extra per additional event
- Currency support (INR/USD)
- Enter 5 scrambles per event
- Manage competitions (view/delete)
Competition System
- Competition detail page with registration
- Event selection (checkboxes)
- FREE registration (one-click)
- Razorpay payment integration
- Payment verification (server-side)
- Competition status (UPCOMING/LIVE/ENDED)
- Registration tracking
WCA Timer (/compete/[competitionId]/[eventId])
- 15-second inspection countdown
- Audio beeps at 8s and 5s
- Auto +2 penalty (15-17 seconds)
- Auto DNF (>17 seconds)
- Space bar controls
- Scramble reveal (locked after reveal)
- Refresh protection (warns before unload)
- Auto-save solves to Firestore
- Auto-move to next scramble
- Attempt tracking (1/5, 2/5, etc.)
Leaderboard (/leaderboard/[competitionId])
- Public access (no auth required)
- Multi-event tabs
- Ao5 calculation (drop best/worst)
- DNF handling
- Sort by average, then best single
- Medal badges for top 3
- Display: Rank, Username, WCA ID, Country, All 5 solves, Average, Best
Profile Page (/profile)
- View and edit profile
- Display: WCA ID, stats, best singles, best averages
- Competition history
- Payment history
- Event-wise personal records
Competitions Listing (/competitions)
- Browse all competitions
- Search functionality
- Filter by status (All/Live/Upcoming/Ended)
- Competition stats display
API Routes (/api/...)
- Payment creation (Razorpay)
- Payment verification
- Free registration
- Submit solve
- Calculate Ao5 results
- Registration status
Security
- Firestore security rules implemented
- Server-side payment verification
- Solve immutability
- Registration permanence
- Role-based access control
/app/
├── app/
│ ├── admin/page.js # Admin Panel
│ ├── competition/[competitionId]/page.js # Competition Detail + Payment
│ ├── compete/[competitionId]/[eventId]/page.js # Timer Component
│ ├── leaderboard/[competitionId]/page.js # Leaderboard
│ ├── competitions/page.js # All Competitions Listing
│ ├── profile/page.js # User Profile
│ ├── auth/
│ │ ├── login/page.js # Login
│ │ └── register/page.js # Register
│ ├── page.js # Homepage
│ ├── layout.js # Root Layout
│ └── api/[[...path]]/route.js # API Routes
├── contexts/
│ └── AuthContext.js # Auth State Management
├── lib/
│ ├── firebase.js # Firebase Config
│ ├── wcaEvents.js # 17 WCA Events
│ └── wcaId.js # WCA ID Generator
├── components/ui/ # shadcn Components
├── .env.local # Environment Variables
├── firestore.rules # Firestore Security Rules
├── PENDING_FEATURES.md # Roadmap
└── package.json # Dependencies
Create Firebase Project:
- Go to https://console.firebase.google.com
- Create a new project
- Enable Authentication (Email/Password + Google)
- Create Firestore Database (Production mode)
Configure Firebase:
- All config is already in
/app/lib/firebase.js - Update
.env.localif needed
Deploy Firestore Rules:
cd /app
firebase deploy --only firestore:rulesGet API Keys:
- Go to https://dashboard.razorpay.com
- Navigate to Settings → API Keys
- Copy Key ID and Secret
Already Configured:
NEXT_PUBLIC_RAZORPAY_KEY_ID=rzp_live_kyn4dKuIvsesAX
RAZORPAY_KEY_SECRET=28uEFtbhWrRp7RhPiS2uyuvY
First user to register with mail becomes admin automatically.
- Login as admin (midhun.speedcuber@gmail.com)
- Go to Admin Panel (shield icon in header)
- Create Competition:
- Enter name, description, dates
- Select FREE or PAID
- Choose pricing model
- Select events (e.g., 3x3, 2x2, Pyraminx)
- Enter 5 scrambles for each event
- Submit
- Register/Login
- Browse Competitions (Home or /competitions)
- View Competition Detail
- Select Events (checkboxes)
- Register:
- FREE: Click "Register (Free)"
- PAID: Click "Pay & Register" → Razorpay checkout → Complete payment
- Start Competition
- For each solve:
- Click "Reveal Scramble"
- Hold SPACE to start 15s inspection
- Press SPACE to start solve
- Press SPACE to stop timer
- Auto-submits and moves to next
- After 5 solves: Auto-redirect to leaderboard
Firestore Rules (/app/firestore.rules):
- ✅ Only admin can create/edit/delete competitions
- ✅ Users can only write their own solves
- ✅ Solve records are immutable
- ✅ Registration records are permanent
- ✅ Payment records are read-only (except server)
- ✅ Leaderboard is publicly readable
API Security:
- Server-side payment verification (SHA256 HMAC)
- User ID validation on all operations
- Competition status checks
- Registration duplicate prevention
- Push to GitHub:
git init
git add .
git commit -m \"MCUBES Platform Complete\"
git branch -M main
git remote add origin YOUR_REPO_URL
git push -u origin main- Import to Vercel:
- Go to https://vercel.com
- Import GitHub repository
- Framework: Next.js
- Add Environment Variables:
NEXT_PUBLIC_FIREBASE_API_KEY=...
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=...
NEXT_PUBLIC_FIREBASE_PROJECT_ID=...
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=...
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=...
NEXT_PUBLIC_FIREBASE_APP_ID=...
NEXT_PUBLIC_ADMIN_EMAIL=midhun.speedcuber@gmail.com
NEXT_PUBLIC_RAZORPAY_KEY_ID=rzp_live_kyn4dKuIvsesAX
RAZORPAY_KEY_SECRET=28uEFtbhWrRp7RhPiS2uyuvY
-
Deploy
-
Deploy Firestore Rules:
firebase deploy --only firestore:rulesFirestore Structure:
users/
- id, email, role, wcaStyleId, displayName, country, photoURL, createdAt
competitions/
- id, name, description, startDate, endDate, type, pricingModel
- flatPrice, basePrice, extraPrice, currency, solveLimit, events
- scrambles (object: { eventId: [scr1, scr2, scr3, scr4, scr5] })
registrations/
- id: {userId}_{competitionId}
- userId, competitionId, events, paymentId, status, registeredAt
solves/
- id, userId, competitionId, eventId, attemptNumber
- time, penalty, timestamp
results/
- id: {userId}_{competitionId}_{eventId}
- userId, competitionId, eventId, times, average, bestSingle
payments/
- id, userId, competitionId, paymentId, orderId
- amount, currency, status, createdAt
Authentication:
- Register with email/password
- Login with email/password
- Login with Google
- WCA ID generated correctly
- Admin role assigned to midhun.speedcuber@gmail.com
Admin:
- Create FREE competition
- Create PAID competition (flat pricing)
- Create PAID competition (per event)
- Create PAID competition (base + extra)
- Enter scrambles for multiple events
- View competitions list
- Delete competition
User Registration:
- Register for FREE competition
- Select multiple events
- Complete Razorpay payment (test mode)
- Verify registration status
Competition Flow:
- Start competition
- Reveal scramble
- 15-second inspection works
- Beeps at 8s and 5s
- +2 penalty applied correctly
- DNF applied correctly
- Timer stops correctly
- Solve auto-submits
- Moves to next scramble
- Complete 5 solves
Leaderboard:
- View leaderboard without login
- Results sorted correctly
- Ao5 calculated correctly
- DNF handled correctly
- Medal badges show for top 3
- Switch between events
Profile:
- View profile stats
- Edit display name
- Edit country
- View competition history
- View payment history
- View best singles
- View best averages
Competitions Listing:
- View all competitions
- Filter by status (Live/Upcoming/Ended)
- Search competitions
- Click to view detail
- Firebase Auth handles login/signup
GET /competitions(via Firestore)POST /api/competitions(admin only)
POST /api/payment/create-order- Create Razorpay orderPOST /api/payment/verify- Verify payment signaturePOST /api/competition/register- Free registrationGET /api/competition/registration-status?userId&competitionId
POST /api/competition/submit-solve- Submit solve timePOST /api/competition/calculate-results- Calculate Ao5
- 3x3x3 Cube
- 2x2x2 Cube
- 4x4x4 Cube
- 5x5x5 Cube
- 6x6x6 Cube
- 7x7x7 Cube
- 3x3x3 Blindfolded
- 3x3x3 Fewest Moves
- 3x3x3 One-Handed
- Clock
- Megaminx
- Pyraminx
- Skewb
- Square-1
- 4x4x4 Blindfolded
- 5x5x5 Blindfolded
- 3x3x3 Multi-Blind
Payment Not Working:
- Check Razorpay keys in
.env.local - Test with Razorpay test mode first
- Check browser console for errors
Timer Issues:
- Ensure audio context is initialized (user interaction required)
- Check space bar event listeners
- Verify Firestore connection
Firebase Errors:
- Verify Firestore rules are deployed
- Check Firebase console for quota limits
- Ensure authentication is enabled
Optimizations:
- Firestore indexes for fast queries
- Client-side caching
- Lazy loading of components
- Optimized images
- Email verification
- Forgot password flow
- Export leaderboard to CSV
- Mobile app
- Real-time leaderboard updates
- Push notifications
- Multi-language support
- Practice mode
For issues:
- Check Firestore rules are deployed
- Verify environment variables
- Check browser console
- Review Firebase console
MIT License
Built with: Next.js 14, Firebase, Razorpay, Tailwind CSS, shadcn/ui
Platform is 100% COMPLETE and PRODUCTION READY! 🎉