A competitive coding contest platform. Participants get a 5×5 BINGO board of buggy code snippets — fix the bugs, pass test cases, and complete BINGO patterns for bonus points.
Requires Bun and a PostgreSQL connection.
bun install # Install dependencies
cp .env.example .env # Configure DATABASE_URL, JUDGE0_HOST, etc.
bun run scripts/sync_db.js # Seed problems from qns/ into PostgreSQL
bun start # Start server on http://localhost:3001- Register a team name and pick a language (Python / C / C++ / Java).
- Click any cell on the 5×5 Bingo grid to open a problem.
- Read the statement, input/output format, constraints, and sample I/O.
- Fix the buggy starter code in the Monaco editor.
- Press Submit (
Ctrl/Cmd+Enter) — code is judged against test files via Judge0. - Complete rows, columns, or diagonals for bonus points.
The admin dashboard at /admin is the primary way to manage a live contest.
- Set
ADMIN_SECRET_KEYin.envand restart. - Log in at
/adminwith your key. - From the dashboard you can:
| Tab | What you can do |
|---|---|
| Overview | See contest status, team count, active problems at a glance |
| Contest Settings | Edit start time (native date picker), duration, rate limit, timezone — takes effect immediately |
| Grid Layout | Drag-and-drop problems into the 5×5 BINGO grid, randomize, save live |
| Question Bank | Enable/disable problems, or create new problems directly with a form (title, statement, constraints, sample I/O) — no JSON editing needed |
| Teams | View leaderboard, scores, solved counts, reset teams |
You can create problems two ways:
Go to Question Bank → + New Problem. Fill in title, difficulty, statement, input/output format, constraints, sample I/O. The problem is immediately added to the database and available in the grid editor.
All problem metadata lives in qns/questions.json and test cases in qns/tests/. After editing, run:
bun run scripts/sync_db.js # Upserts everything into PostgreSQLNo server restart needed — changes are live on next page load.
{
"id": 0,
"title": "Boundary Elements of a Matrix",
"difficulty": "Medium",
"problem_statement": "You are given a matrix of N×M integers...",
"input_format": "First line: T (test cases). For each: N M, then N lines of M integers.",
"output_format": "For each test case, print boundary elements in clockwise order.",
"constraints": "1 ≤ T ≤ 100\n1 ≤ N, M ≤ 100",
"sample_input": "2\n3 4\n1 2 3 4\n5 6 7 8\n9 10 11 12\n1 5\n4 5 6 7 8",
"sample_output": "1 2 3 4 8 12 11 10 9 5\n4 5 6 7 8",
"starter_code": {
"python": "# buggy code here",
"c": "// buggy code here",
"cpp": "// buggy code here",
"java": "// buggy code here"
}
}bingo/
├── server.js Bun HTTP server
├── .env Secrets (gitignored)
│
├── qns/
│ ├── questions.json Problem metadata (bulk import source)
│ └── tests/ Full judge test cases (0_input.txt, 0_output.txt ...)
│
├── scripts/
│ └── sync_db.js Seed PostgreSQL from qns/ files
│
├── src/
│ ├── api.js Public API routes (register, submit, leaderboard...)
│ ├── admin.js Admin API routes (settings, grid, questions...)
│ ├── db.js PostgreSQL schema + pool
│ ├── judge.js Judge0 integration
│ ├── submission.js Submission pipeline (rate-limit, scoring)
│ ├── settings.js Live contest settings (DB-backed)
│ ├── game.js Bingo grid scoring
│ └── env.js .env loader
│
└── public/ Static frontend (ES modules)
├── index.html Contest page
├── admin.html Admin dashboard
├── leaderboard.html Public leaderboard
├── app.js Main contest entry point
├── leaderboard.js Leaderboard logic
├── styles.css Design system
├── leaderboard.css
├── admin/
│ ├── app.js Admin entry point
│ ├── api.js API utilities (showToast, apiRequest)
│ ├── state.js Shared admin state
│ ├── overview.js Dashboard overview
│ ├── settings.js Contest settings panel
│ ├── questions.js Question bank panel
│ ├── teams.js Teams panel
│ ├── grid.js Grid layout editor
│ └── preview.js Question preview modal
├── components/
│ ├── game.js Bingo game UI
│ ├── editor.js Monaco editor wrapper
│ └── resizer.js Panel resize handles
├── utils/
│ └── toast.js Toast notifications
└── data/
└── languages.js Language config (Monaco IDs, Judge0 IDs)
| Method | Route | Description |
|---|---|---|
| POST | /api/register |
Register team |
| GET | /api/contest_status |
Start time, duration, rate limit |
| GET | /api/team_status |
Team score, solved cells, grid |
| GET | /api/leaderboard |
All teams sorted by score |
| GET | /api/questions/manifest |
Active problem list |
| GET | /api/questions/:id |
Problem detail + starter code |
| POST | /api/judge/submit |
Submit code for judging |
| PATCH | /api/admin/questions/:id |
Update problem fields |
| POST | /api/admin/questions |
Create new problem |
| GET/POST | /api/admin/settings |
Read/write contest settings |
| GET/POST | /api/admin/grid |
Read/write bingo grid |
| GET | /api/admin/teams |
List all teams |
| POST | /api/admin/teams/reset |
Reset team score |
All admin routes require x-admin-key header matching ADMIN_SECRET_KEY in .env.
| Layer | Technology |
|---|---|
| Frontend | Vanilla HTML5, CSS3, JavaScript (ES modules) · Monaco Editor |
| Backend | Bun HTTP server |
| Database | PostgreSQL (Neon) |
| Code Execution | Judge0 CE API |
| Testing | Jest |