Skip to content

devsharmagit/leetgrind

Repository files navigation

🎯 LeetGrind

Competitive LeetCode Progress Tracking for Teams

Next.js TypeScript PostgreSQL Prisma License

FeaturesTech StackSetupDeployment


What is LeetGrind?

LeetGrind is a competitive progress tracking platform for LeetCode teams. It automatically fetches daily statistics, calculates ranking points, and generates leaderboard snapshots for groups.

Key Features

  • Automated Daily Updates: Vercel cron jobs fetch LeetCode stats at midnight UTC
  • Team Leaderboards: Track progress across groups with 5+ members
  • Immutable History: Append-only architecture preserves complete statistical history
  • Smart Scoring: Weighted algorithm considering problem difficulty, total solved, and global rank
  • Google OAuth: Secure authentication via NextAuth v5

Architecture

leetgrind

Key Components

Component Implementation
Auth NextAuth v5 (Google OAuth)
Cron Auth x-vercel-cron header (prod) / Bearer ${CRON_SECRET} (test)
Rate Limiting Upstash Redis sliding window (optional, disabled by default)
Batch Processing 5 concurrent requests, 1s inter-batch delay, 5s timeout
Scoring (total×10) + (easy×1) + (med×3) + (hard×5) + max(0, 5M-rank)/1000

Scoring Algorithm

rankingPoints = (totalSolved * 10) 
              + (easySolved * 1) 
              + (mediumSolved * 3) 
              + (hardSolved * 5) 
              + max(0, 5000000 - globalRank) / 1000

Leaderboard sorted by:

  1. Ranking points (descending)
  2. Global rank (ascending, tiebreaker)
  3. Username (alphabetical, stability)

Technology Stack

Frontend

Next.js React TypeScript TailwindCSS

Backend

Bun Prisma PostgreSQL Zod

Infrastructure

Vercel Docker

Layer Technology
Runtime Node.js via Bun
Framework Next.js 16 (App Router), React 19
Database PostgreSQL 16
ORM Prisma 7 (generated to src/generated/prisma)
Auth NextAuth v5 (Google OAuth)
Styling Tailwind CSS 4, shadcn/ui
Charts Recharts 2
Validation Zod 4
Rate Limiting Upstash Redis + @upstash/ratelimit
Cron Vercel Cron Jobs
Testing Jest 30, React Testing Library
Deployment Vercel

Setup

Prerequisites

  • Bun 1.x or Node.js 20+
  • PostgreSQL 16
  • Docker (optional)
  • Google OAuth credentials

Quick Start

  1. Clone and install:
git clone <repository-url>
cd leetgrind
bun install
  1. Start PostgreSQL:
docker-compose up -d
# Wait for "healthy" status
docker-compose ps
  1. Configure environment (copy .env.example to .env):
DATABASE_URL="postgresql://postgres:password@localhost:5432/leetgrind"
NEXTAUTH_SECRET="<openssl rand -base64 32>"
GOOGLE_CLIENT_ID="<from Google Cloud Console>"
GOOGLE_CLIENT_SECRET="<from Google Cloud Console>"
CRON_SECRET="<openssl rand -base64 32>"
  1. Setup database:
bunx prisma generate
bunx prisma migrate deploy
  1. Run development server:
bun run dev
# → http://localhost:3000

Google OAuth Setup

  1. Go to Google Cloud Console
  2. Create OAuth 2.0 credentials
  3. Add redirect URI: http://localhost:3000/api/auth/callback/google
  4. Copy Client ID and Client Secret to .env

Production Deployment (Vercel)

  1. Push repository to GitHub/GitLab/Bitbucket
  2. Import project to Vercel
  3. Configure environment variables in Vercel dashboard (same as .env)
  4. Ensure CRON_SECRET is set (required even though Vercel uses x-vercel-cron header)
  5. Deploy (Vercel automatically detects vercel.json cron configuration)

Cron jobs authenticate automatically via x-vercel-cron: 1 header in production.

Testing

# All tests (unit + API integration)
bun test

# Unit tests only
bun run test:unit

# Database integration tests (requires DATABASE_URL)
bun run test:db

# Watch mode
bun run test:watch

# Coverage
bun run test:coverage

Test Cron Locally

curl -X POST http://localhost:3000/api/cron/update-stats \
  -H "Authorization: Bearer ${CRON_SECRET}"

Architecture Decisions

Decision Rationale Tradeoff
Immutable Snapshots Never update DailyStat records; preserves historical accuracy, simplifies concurrency ~1KB/profile/day storage (365MB/year for 1K profiles)
Batch Processing 5 concurrent + 1s delay avoids LeetCode IP bans Processes 100 profiles in ~25 seconds
Server Actions Type-safe, auto-deduplication, less boilerplate Less flexible for external API consumers
JSON Snapshots Single-row queries instead of complex joins Requires Zod validation at app layer
Optional Rate Limiting Free tier friendly (Upstash 10K req/day) Enable for >500 users or public deployments

Known Limitations

  • No Official LeetCode API: Relies on undocumented GraphQL endpoint
  • Username Changes: Break historical tracking (no UUID identity)
  • UTC Normalization: Snapshots at midnight UTC (timezone-dependent)
  • Daily Updates Only: No realtime stats (24h refresh cycle)

Scalability

Metric Bottleneck Mitigation
DB Connections ~50 concurrent Add ?connection_limit=20 to DATABASE_URL
Cron Timeout 10 min (Vercel) Shard by profile ID range
Storage Multi-TB limit Archive old snapshots (>90d) to S3

Roadmap

  • Multi-provider auth (GitHub, Discord)
  • Webhook notifications (Slack/Discord)
  • Streak tracking
  • Difficulty-specific leaderboards
  • Public embeddable leaderboard widgets

⭐ Star on GitHub📖 Documentation🐛 Report Bug

MIT License • Built with Bun & Next.js

About

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published