A complete full-stack real-time leaderboard system built with modern web technologies. Features user authentication, game management, score tracking, live leaderboards, direct messaging, and social features.
- โ JWT Authentication - Secure access & refresh token rotation
- โ Role-Based Access Control - User/Admin permissions
- โ Game Management - CRUD operations with image uploads
- โ Score Submission - Real-time score tracking with metadata
- โ Live Leaderboards - Global, per-game, and daily rankings
- โ Direct Messaging - Real-time chat with unread tracking
- โ Social Features - Friend requests, user connections
- โ WebSocket Support - Live updates via Socket.IO
- โ Responsive UI - Modern React interface with Tailwind CSS
- Runtime: Node.js with TypeScript
- Framework: Express 5.1
- Database: PostgreSQL (via Prisma ORM)
- Cache: Redis 5.9
- Real-time: Socket.IO 4.8
- Validation: Zod
- Auth: JWT (jsonwebtoken)
- File Upload: Multer + Cloudinary
- Security: bcrypt password hashing
- Framework: React 18 with TypeScript
- Build Tool: Vite
- State Management: Zustand
- Data Fetching: TanStack Query (React Query)
- Styling: Tailwind CSS
- Forms: React Hook Form + Zod
- Real-time: Socket.IO Client
- Icons: Lucide React
- Animations: Framer Motion
- Node.js >= 18.x
- PostgreSQL >= 14.x
- Redis >= 6.x
- Cloudinary account (for image uploads)
# Install backend dependencies
cd server
npm install
# Install frontend dependencies
cd ../client
npm install
# Return to root
cd ..Create a .env file in the server/ directory:
# Server
PORT=5000
NODE_ENV=development
# Database (PostgreSQL)
DATABASE_URL="postgresql://user:password@localhost:5432/leaderboard?schema=public"
# Redis
REDIS_URL="redis://localhost:6379"
# JWT Secrets
JWT_SECRET="your-super-secret-jwt-key-here"
JWT_REFRESH_TOKEN_SECRET="your-refresh-token-secret-here"
# Cloudinary (for image uploads)
CLOUDINARY_CLOUD_NAME="your-cloud-name"
CLOUDINARY_API_KEY="your-api-key"
CLOUDINARY_API_SECRET="your-api-secret"cd server
# Generate Prisma Client
npx prisma generate
# Run migrations
npx prisma migrate dev
# (Optional) Open Prisma Studio
npx prisma studio# Terminal 1: Start Backend Server
cd server
npm run dev
# Server will start on http://localhost:5000
# Terminal 2: Start Frontend Client
cd client
npm run dev
# Client will start on http://localhost:5173 (or next available port)Open your browser and navigate to http://localhost:5173 to access the full application.
POST /v1/api/auth/register - Register new user
POST /v1/api/auth/login - Login (returns access + refresh tokens)
POST /v1/api/auth/refresh - Refresh access token
POST /v1/api/auth/logout - Logout (revoke refresh token)
GET /v1/api/users - Get all users (auth required)
GET /v1/api/users/:id - Get user by ID (auth required)
PUT /v1/api/users/:id - Update user (own profile or admin)
DELETE /v1/api/users/:id - Delete user (own profile or admin)
GET /v1/api/games - Get all games (public)
GET /v1/api/games/:id - Get game details (public)
POST /v1/api/games - Create game (admin only, supports image)
PUT /v1/api/games/:id - Update game (admin only, supports image)
DELETE /v1/api/games/:id - Delete game (admin only)
POST /v1/api/scores/:id - Submit score for game (auth required)
GET /v1/api/scores/:id/best - Get user's best score (auth required)
GET /v1/api/leaderboard/global - Global leaderboard
GET /v1/api/leaderboard/game/:id - Game-specific leaderboard
GET /v1/api/leaderboard/game/:id/daily - Daily leaderboard
GET /v1/api/leaderboard/game/:id/rank - User's rank (auth required)
Query params: ?limit=100 (default: 100)
POST /v1/api/messages/ - Send message (auth required)
GET /v1/api/messages/conversation/:id - Get conversation (auth required)
POST /v1/api/messages/mark-read - Mark messages as read (auth required)
GET /v1/api/messages/unread-count - Get unread count (auth required)
socket.emit("joinGameRoom", gameId); // Join game room for updates
socket.emit("leaveGameRoom", gameId); // Leave game roomsocket.on("leaderboard:update", (data) => {
// { gameId, userId, score, rank }
});
socket.on("message:new", (message) => {
// New message received
});
socket.on("message:sent", (message) => {
// Message sent confirmation
});
socket.on("message:unread_count", ({ count }) => {
// Updated unread message count
});const socket = io("http://localhost:5000", {
auth: {
token: "your-jwt-access-token",
},
});POST /v1/api/auth/register
Content-Type: application/json
{
"username": "player123",
"email": "player@example.com",
"password": "securePassword123"
}POST /v1/api/auth/login
Content-Type: application/json
{
"email": "player@example.com",
"password": "securePassword123"
}
# Response:
{
"message": "Login Successful",
"accessToken": "eyJhbGc...",
"refreshToken": "eyJhbGc...",
"user": {
"userId": "uuid",
"name": "player123",
"email": "player@example.com",
"role": "USER"
}
}POST /v1/api/games
Authorization: Bearer <admin-access-token>
Content-Type: multipart/form-data
slug: tetris-classic
title: Tetris Classic
description: Classic block-stacking puzzle game
metadata: {"maxLevel": 20, "scoreMultiplier": 100}
image: <file>POST /v1/api/scores/:gameId
Authorization: Bearer <access-token>
Content-Type: application/json
{
"score": 15000,
"meta": {
"level": 10,
"lines": 45,
"duration": 320
}
}
# Response:
{
"success": true,
"saved": { /* score object */ },
"leaderboardUpdated": true,
"rank": 3,
"score": 15000
}GET /v1/api/leaderboard/game/:gameId?limit=50
# Response:
[
{
"rank": 1,
"userId": "uuid",
"score": 25000,
"user": {
"id": "uuid",
"username": "topplayer",
"displayName": "Top Player",
"avatarUrl": "https://..."
}
},
...
]POST /v1/api/messages
Authorization: Bearer <access-token>
Content-Type: application/json
{
"toUserId": "recipient-uuid",
"content": "Hello! Good game!"
}- Responsive Design - Mobile-first approach with Tailwind CSS
- Modern UI Components - Clean, accessible interface
- Real-time Updates - Live leaderboard and message updates
- Form Validation - Client-side validation with error handling
- Loading States - Smooth loading indicators and skeletons
- User registration and login
- Form validation and error handling
- Secure token management
- User statistics and overview
- Quick action cards
- Top players preview
- Browse available games
- Game details with leaderboard preview
- Score submission with metadata support
- Global leaderboard rankings
- Game-specific leaderboards
- Real-time rank updates
- Daily leaderboard support
- Friend requests (send, accept, reject)
- Friends list management
- Real-time messaging system
- Unread message counters
- Game management (CRUD operations)
- User statistics overview
- Admin-only features
- User - Authentication, profile, roles
- Game - Game definitions with metadata
- Score - User scores per game
- Message - Direct messages between users
- RefreshToken - JWT refresh token management
- Friendship - Social connections
- Leaderboard - Cached in Redis sorted sets
Optimized queries with composite indexes on:
Score:[gameId, createdAt],[userId]Message:[toUserId, isRead],[fromUserId, createdAt],[toUserId, createdAt]
- โ Password hashing with bcrypt (10 rounds)
- โ JWT access tokens (1h expiry)
- โ Refresh token rotation (2d expiry)
- โ Token revocation on logout
- โ Role-based authorization
- โ Input validation with Zod
- โ SQL injection protection (Prisma)
- โ CORS configuration
.
โโโ client/ # React Frontend
โ โโโ public/ # Static assets
โ โโโ src/
โ โ โโโ api/ # API endpoints & axios config
โ โ โโโ components/ # Reusable UI components
โ โ โ โโโ common/ # Basic components (Button, Input, etc.)
โ โ โ โโโ features/ # Feature-specific components
โ โ โ โโโ layout/ # Layout components
โ โ โโโ contexts/ # React contexts (legacy)
โ โ โโโ hooks/ # Custom React hooks
โ โ โโโ lib/ # Utilities (queryClient, utils)
โ โ โโโ pages/ # Page components
โ โ โ โโโ auth/ # Authentication pages
โ โ โ โโโ dashboard/ # Dashboard pages
โ โ โ โโโ games/ # Game-related pages
โ โ โ โโโ leaderboard/ # Leaderboard pages
โ โ โ โโโ chat/ # Chat pages
โ โ โ โโโ friends/ # Friends pages
โ โ โ โโโ profile/ # Profile pages
โ โ โ โโโ admin/ # Admin pages
โ โ โโโ providers/ # Context providers
โ โ โโโ stores/ # Zustand stores
โ โ โโโ styles/ # Global styles
โ โ โโโ types/ # TypeScript type definitions
โ โ โโโ utils/ # Helper functions
โ โโโ package.json
โ โโโ tsconfig.json
โ โโโ vite.config.ts
โ โโโ README.md
โโโ server/ # Node.js Backend
โ โโโ prisma/
โ โ โโโ schema.prisma # Database schema
โ โ โโโ migrations/ # Migration history
โ โโโ src/
โ โ โโโ config/ # Configuration files
โ โ โ โโโ db.ts # Prisma client
โ โ โ โโโ redis.ts # Redis client
โ โ โ โโโ cloudinary.ts # Cloudinary config
โ โ โ โโโ socket.ts # Socket.IO setup
โ โ โโโ controllers/ # Request handlers
โ โ โโโ middleware/ # Auth & role middleware
โ โ โโโ routes/ # API route definitions
โ โ โโโ schemas/ # Zod validation schemas
โ โ โโโ services/ # Business logic
โ โ โโโ types/ # TypeScript types
โ โ โโโ utils/ # Helper functions
โ โ โโโ index.ts # App entry point
โ โโโ .env # Environment variables
โ โโโ package.json
โ โโโ tsconfig.json
โ โโโ README.md
โโโ README.md # This file
cd server
npm run build
npm startcd client
npm run build
# Dist files will be in client/dist/- Set
NODE_ENV=production - Use secure JWT secrets (32+ characters)
- Configure production database URL
- Enable Redis persistence
- Set up CORS allowed origins
- Use managed Cloudinary account
- Database: Railway, Neon, Supabase
- Redis: Redis Cloud, Upstash
- Backend Hosting: Railway, Render, Fly.io
- Frontend Hosting: Vercel, Netlify, Railway
- CDN: Cloudinary (images)
- Redis Caching - Leaderboard data in sorted sets
- Database Indexes - Optimized query performance
- Connection Pooling - Prisma connection management
- Pagination - Cursor-based for messages, limit-based for leaderboards
- WebSocket - Efficient real-time updates
-
Backend Setup:
- Register user โ Login โ Get tokens
- Create admin user in DB:
UPDATE "User" SET role = 'ADMIN' WHERE email = '...' - Create games with admin token
- Submit scores and verify leaderboard updates
-
Frontend Testing:
- Register/login through the UI
- Browse games and submit scores
- Check real-time leaderboard updates
- Test friend requests and messaging
- Verify responsive design on mobile/desktop
-
Real-time Features:
- Test Socket.IO connections
- Open multiple browser tabs to verify live updates
- Test message delivery and friend request notifications
UPDATE "User" SET role = 'ADMIN' WHERE email = 'admin@example.com';npx prisma generateEnsure Redis is running:
redis-server
# or
docker run -d -p 6379:6379 redisnpx prisma migrate reset # โ ๏ธ Drops all data
npx prisma migrate devChange PORT in .env or kill process:
# Windows
netstat -ano | findstr :5000
taskkill /PID <PID> /F
# Linux/Mac
lsof -ti:5000 | xargs kill -9{
"start": "node dist/index.js",
"build": "tsc",
"dev": "nodemon --watch src --ext ts --exec \"npm run build && npm run start\"",
"postinstall": "prisma generate"
}{
"dev": "vite",
"build": "tsc -b && vite build",
"preview": "vite preview"
}- Fork the repository
- Create feature branch:
git checkout -b feature/amazing-feature - Commit changes:
git commit -m 'Add amazing feature' - Push to branch:
git push origin feature/amazing-feature - Open Pull Request
ISC
Built with โค๏ธ for real-time gaming experiences - Full-stack application with modern React frontend and robust Node.js backend.
Happy Coding! ๐ฎ๐