A full-stack online judge and competitive programming platform โ built with Next.js 16, MongoDB, Redis, and Docker-sandboxed code execution.
CodeArena is an online competitive programming platform that allows users to browse coding problems, write and submit solutions in multiple programming languages, and compete in timed contests โ all from a browser-based code editor. The platform judges submitted code automatically by executing it inside isolated Docker containers and comparing its output against predefined test cases.
It is a team-built full-stack application following a monolithic Next.js architecture with a clean separation between frontend features, API controllers, business services, and database models.
Real containerized code runner. Your solutions execute in isolated, secure Docker containers with strict resource limits for fair and safe evaluations.
Beyond pass/fail. Get granular feedback with standard verdicts including ACCEPTED, TLE, MLE, and detailed RUNTIME_ERROR reports.
Real secure login system. Enterprise-grade security combining Firebase for identity and JWT for stateless session management.
Search, filter, and paginate through challenges by difficulty, tags, or title to find the perfect problem for your skill level.
Note
CodeArena is a monolithic Next.js application where both the frontend and backend live in the same codebase. The App Router handles page-level rendering while /api/* routes act as a REST API. The architecture separates concerns into Controllers โ Services โ Models layers within that monolith.
Monaco editor POSTs to POST /api/problems/[id]/submit with language and source code.
The request passes through middleware that verifies the user's JWT before reaching the controller.
The submission controller creates a MongoDB document with status PENDING and enqueues a BullMQ job.
A BullMQ worker (backed by Redis) processes the job by calling the judge service.
The judge calls POST /api/evaluation/execute which uses dockerode โ docker-proxy โ Docker Engine to create a sandboxed container.
Stdout is compared to expected output. Timing and memory are measured. A verdict is produced.
The submission document is updated with the final verdict (e.g., ACCEPTED, WRONG_ANSWER) and execution stats.
Frontend polls GET /api/evaluation/status or GET /api/submissions/[id] until the verdict is available.
codearena/
โโโ src/
โ โโโ app/ # Next.js App Router
โ โ โโโ (pages)/ # Frontend page routes
โ โ โ โโโ page.jsx # Landing page (/)
โ โ โ โโโ login/ # /login
โ โ โ โโโ signup/ # /signup
โ โ โ โโโ problems/ # /problems + /problems/[id]
โ โ โ โโโ leaderboard/ # /leaderboard
โ โ โ โโโ profile/ # /profile, /profile/[id]
โ โ โ โโโ practice/ # /practice (placeholder)
โ โ โ โโโ test-docker/ # /test-docker (dev tool)
โ โ โโโ api/ # REST API routes
โ โ โโโ auth/ # Auth endpoints
โ โ โโโ problems/ # Problem CRUD + submit
โ โ โโโ submissions/ # Submission read
โ โ โโโ evaluation/ # Judge execution endpoints
โ โ โโโ contests/ # Contest management
โ โ โโโ user/ # Per-user queries
โ โ โโโ users/ # User listing/lookup
โ โ โโโ admin/ # Admin log management
โ โ โโโ health/ # Health check
โ โ
โ โโโ components/ # Shared UI components
โ โ โโโ ui/ # Shadcn/Radix base components
โ โ โโโ layout/ # Header, Footer, Sidebar, Nav
โ โ โโโ shared/ # Cards, Badges, Loaders, etc.
โ โ
โ โโโ features/ # Feature-scoped frontend modules
โ โ โโโ auth/ # Login/signup forms & logic
โ โ โโโ problems/ # Problem list, filters, workspace
โ โ โโโ contests/ # Contest UI
โ โ โโโ leaderboard/ # Leaderboard UI
โ โ โโโ profile/ # Profile page sections
โ โ
โ โโโ controllers/ # API route handlers (thin layer)
โ โโโ services/ # Business logic / data layer
โ โโโ models/ # Mongoose schemas
โ โโโ middlewares/ # Request middleware
โ โโโ lib/ # Utilities & infrastructure
โ
โโโ docker/ # Docker build scripts
โโโ redis/ # Redis config files
โโโ public/ # Static assets
โโโ Dockerfile # Multi-stage production build
โโโ docker-compose.yml # Production stack
โโโ package.json| Field | Type | Description |
|---|---|---|
_id | ObjectId | MongoDB document ID |
uid | String | Firebase UID (synced from client auth) |
username | String | Unique display name |
email | String | User email address (unique) |
passwordHash | String | bcryptjs-hashed password |
role | String | Enum: user | admin |
solvedProblems | ObjectId[] | References to solved Problem documents |
createdAt | Date | Account creation timestamp |
| Field | Type | Description |
|---|---|---|
_id | ObjectId | Document ID |
title | String | Problem title |
slug | String | URL-friendly identifier |
difficulty | String | Enum: easy | medium | hard |
tags | String[] | Algorithm/topic tags (e.g., "dp", "graph") |
description | String | Markdown problem statement (supports LaTeX via KaTeX) |
inputFormat | String | Input specification |
outputFormat | String | Output specification |
testCases | Array | Array of {input, expectedOutput} objects |
timeLimit | Number | Time limit in milliseconds |
memoryLimit | Number | Memory limit in MB |
sampleTestCases | Array | Publicly visible sample cases |
| Field | Type | Description |
|---|---|---|
_id | ObjectId | Document ID |
userId | ObjectId | Reference to User |
problemId | ObjectId | Reference to Problem |
language | String | Enum: cpp | python | java | javascript |
code | String | Raw source code |
verdict | String | One of the 9 possible verdicts |
executionTime | Number | Runtime in ms |
memoryUsed | Number | Memory consumption in KB |
testCaseResults | Array | Per-test-case result details |
createdAt | Date | Submission timestamp |
| Field | Type | Description |
|---|---|---|
_id | ObjectId | Document ID |
title | String | Contest name |
description | String | Contest description |
startTime | Date | Contest start datetime |
endTime | Date | Contest end datetime |
problems | ObjectId[] | List of Problem references |
participants | ObjectId[] | Registered user references |
createdBy | ObjectId | Admin user reference |
CodeArena implements a dual-layer authentication strategy combining Firebase Auth on the client side with JWT cookies on the server side.
POST /api/auth/register or POST /api/auth/login โ password hashed with bcryptjs, user stored in MongoDB, JWT issued as an HttpOnly cookie.
POST /api/auth/sync โ client sends Firebase ID token; server verifies it via Firebase Admin SDK, then upserts the user in MongoDB and issues its own JWT cookie.
All protected API routes run through authMiddleware.js which reads and verifies the token HttpOnly cookie using jsonwebtoken.
POST /api/auth/logout โ clears the JWT cookie on the server side.
Security Note
The judge is the most technically complex subsystem of CodeArena. It compiles and executes user-submitted code inside ephemeral Docker containers, measuring execution time and memory, and comparing output against expected test results.
Compiled with g++; fastest execution.
Interpreted; python3 runtime.
Compiled with javac and run on JVM.
Run with Node.js runtime.
CodeArena supports timed competitive contests. Each contest has a defined start time, end time, and a set of problems. Users can register for a contest and make submissions during the contest window. A leaderboard is computed per-contest based on accepted problems and penalty time.
The platform maintains both a global leaderboard and per-contest leaderboards. Rankings are computed by the leaderboard service from submission data stored in MongoDB. The global leaderboard is accessible at /leaderboard and via GET /api/contests/[id]/leaderboard for contest-specific rankings.
| Method | Endpoint | Auth | Description |
|---|---|---|---|
POST | /api/auth/register | None | Create a new account. Body: {username, email, password}. Sets JWT cookie. |
POST | /api/auth/login | None | Authenticate with email/password. Sets JWT cookie on success. |
POST | /api/auth/logout | JWT | Clears the JWT cookie. Logs out the session. |
POST | /api/auth/sync | Firebase Token | Syncs a Firebase-authenticated user to MongoDB. Issues JWT cookie. |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET | /api/problems | Optional | List problems with search (?q=), tag filter, difficulty filter, and pagination (?page=&limit=). Returns solved status if authenticated. |
GET | /api/problems/[id] | Optional | Get a single problem by ID, including description, sample test cases, time/memory limits. |
POST | /api/problems/[id]/submit | JWT Required | Submit code for a problem. Body: {language, code}. Returns submission ID immediately; judging is async. |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
POST | /api/evaluation/execute | Internal | Run code in a Docker container. Body: {language, code, stdin}. Returns stdout, stderr, exitCode. |
POST | /api/evaluation/judge | Internal | Full judge run: execute against all test cases and compute verdict. |
POST | /api/evaluation/test | JWT Required | Run code against a single custom test input (for the "Run" button). Not recorded as a submission. |
GET | /api/evaluation/status | JWT Required | Poll for the current verdict of a pending/judging submission. Query: ?id=submissionId. |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET | /api/contests | None | List all contests (upcoming, active, ended). |
POST | /api/contests | Admin JWT | Create a new contest. |
GET | /api/contests/[id] | None | Get contest details including problems list. |
POST | /api/contests/[id]/register | JWT Required | Register the authenticated user for the contest. |
GET | /api/contests/[id]/participants | None | List all registered participants for the contest. |
GET | /api/contests/[id]/leaderboard | None | Fetch the contest leaderboard, ranked by accepted problems and penalty. |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET | /api/users | JWT | List all users (admin use). |
GET | /api/users/[id] | None | Get public profile data for a user by ID. |
GET | /api/user/problems-status | JWT Required | Returns the authenticated user's solved/attempted problem list. |
GET | /api/submissions | JWT Required | List submissions for the authenticated user (or all, for admins). |
GET | /api/submissions/[id] | JWT Required | Get full details of a specific submission including per-test-case results. |
GET | /api/health | None | Health check endpoint. Returns server/DB/Redis status. |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET | /api/admin/logs | Admin JWT | Retrieve all admin action logs with pagination. |
GET | /api/admin/logs/[id] | Admin JWT | Get a specific admin log entry by ID. |
| Route | Auth | Description |
|---|---|---|
/ | None | Landing page with 3D hero, animations (Three.js, GSAP, Framer Motion) |
/login | None | Email/password + Firebase login form |
/signup | None | Registration form with validation (Zod + React Hook Form) |
/problems | None | Paginated problem browser with search and tag/difficulty filters |
/problems/[id] | JWT for Submit | Problem detail + Monaco editor + Run + Submit |
/leaderboard | None | Global user leaderboard |
/profile | JWT | Own profile page with activity calendar and stats |
/profile/[id] | None | Public profile view for any user |
/profile/settings | JWT | Account settings (avatar, username, etc.) |
/userdashboard | JWT | Personal dashboard: recent submissions, stats, activity |
/practice | None | Placeholder โ "Coming Soon" |
/test-docker | None (dev) | Debug interface to test Docker execution pipeline |
Prerequisites
git clone <repository-url>
cd CodeArena-TeamProject
git checkout development
npm installMONGODB_URI=mongodb://localhost:27017/codearena
JWT_SECRET=your_super_secret_jwt_key
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=your_redis_password
# Firebase (from Firebase Console โ Project Settings โ General)
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_FIREBASE_MEASUREMENT_ID=npm run docker:build
# Runs docker/scripts/build-images.sh
# Builds: judge-cpp, judge-python, judge-java, judge-js Docker imagesnpm run dev
# App available at http://localhost:3000The repository includes a production-ready docker-compose.yml that wires together all services. It runs the app on port 3001 (mapped from internal 3000).
| Service | Image | Port | Purpose |
|---|---|---|---|
mongodb | mongo:latest | 27017 | Primary database with health check and persistent volume |
redis | redis:7 | 6379 | Cache, BullMQ queue, Socket.IO adapter; AOF persistence enabled, 256 MB limit |
app | Local build | 3001โ3000 | Next.js production app; waits for MongoDB and docker-proxy |
docker-proxy | tecnativa/docker-socket-proxy | 2376 (host) | Restricted Docker socket proxy; only exposes CONTAINERS, IMAGES, EXEC, POST |
docker compose up -d --builddocker compose -f docker-compose.yml -f docker-compose.dev.yml up| Variable | Required | Description |
|---|---|---|
MONGODB_URI | โ | Full MongoDB connection string (with auth if applicable) |
JWT_SECRET | โ | Secret key used to sign/verify JWT tokens โ keep this private |
REDIS_HOST | โ | Redis server hostname (e.g., localhost or redis in Docker) |
REDIS_PORT | โ | Redis port (default 6379) |
REDIS_PASSWORD | โ | Redis auth password |
REDIS_URL | โ | Full Redis URL (alternative to HOST/PORT/PASSWORD) |
DOCKER_HOST | โ | Docker API host. Set to http://docker-proxy:2375 in Docker Compose |
NODE_ENV | โ | development | production |
NEXT_PUBLIC_FIREBASE_API_KEY | โ | Firebase project API key (client-side) |
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN | โ | Firebase auth domain |
NEXT_PUBLIC_FIREBASE_PROJECT_ID | โ | Firebase project ID |
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET | โ | Firebase storage bucket |
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID | โ | Firebase messaging sender |
NEXT_PUBLIC_FIREBASE_APP_ID | โ | Firebase app ID |
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID | โ | Firebase Analytics measurement ID |
| Script | Command | Description |
|---|---|---|
npm run dev | next dev | Start Next.js development server with hot reload on port 3000 |
npm run build | next build | Create an optimized production build |
npm run start | next start | Run the production build (requires npm run build first) |
npm run lint | eslint | Run ESLint across the codebase |
npm run docker:build | bash docker/scripts/build-images.sh | Build all language executor Docker images for the judge |
npm run prepare | husky install | Set up Husky Git hooks (auto-runs on npm install) |
Git Hooks
.js, .jsx, .ts, .tsx, .json, .css, .md, .mjs files before each commit, ensuring consistent code formatting.The production Dockerfile uses a 3-stage build to keep the final image lean and secure:
Installs only npm dependencies. Husky is disabled in CI/Docker via ENV HUSKY=0.
Copies deps and source, accepts Firebase env vars as build-time ARGs, and runs next build with telemetry disabled.
Copies only the Next.js standalone output and static assets. Runs as a non-root nextjs user (UID 1001) on port 3000.
CodeArena was built by a six-person team with specialized responsibilities across backend, frontend, and project leadership.
Team Lead
Rabiul Islam
Backend
Arafat Salehin
Backend
AH Muzahid
Frontend
Shahnawas Adeel
Frontend
Abdullah Noman
Frontend
Ummey Salma Tamanna
CodeArena ยท Team Project ยท Next.js 16 ยท MongoDB ยท Docker ยท docs generated April 2026