DEV Community

Cover image for Nemesis - Every Competitive Programmer Has One. I Built a Tracker For Mine.
Srijan Pandey
Srijan Pandey

Posted on

Nemesis - Every Competitive Programmer Has One. I Built a Tracker For Mine.

DEV Weekend Challenge: Passion Edition Submission

This is a submission for Weekend Challenge: Passion Edition

What I Built

Every competitive programmer has a Nemesis — the one person whose Codeforces rating you check before your own morning coffee. As a tribute to my undying (and one-sided) love for competitive programming, I built Nemesis, a head-to-head rivalry tracker that turns that quiet obsession into a living, gamified duel.

Rating is a lagging indicator, it tells you who was better six months ago, not who's grinding right now. So Nemesis computes an Obsession Score, weighted toward current effort (solve velocity, streaks, upsolve discipline) over historical rating. You can be "winning" on obsession while losing on rating, and the app shows that tension instead of hiding it.

The rivalry is also split into weekly rounds — whoever solves more that week wins it, tallied into a running season score. And on demand, Gemini reads the live head-to-head and writes a dry, stats-grounded recap plus a targeted catch-up tip for whoever's behind.

Demo

🔗 Live app: nemesis-cyan.vercel.app

Nemesis dashboard showing obsession score comparison, difficulty breakdown dial, season score, and a Gemini-generated recap between two rivals

Code

Nemesis — Your CP Rivalry, Narrated

Built for the "Passion" weekend challenge. Every competitive programmer has one — the person whose rating you check before your own. Nemesis turns that rivalry into a living head-to-head: real rating data, a composite "Obsession Score" that rewards current grind over past glory, and Gemini-written recaps that read like sports commentary instead of a boring stats table.

Prize category: Best use of Google AI — Gemini is the actual differentiator here, not a bolt-on. See AI Studio Handoff below.


Architecture

nemesis/
├── backend/          MERN API — Express + MongoDB
│   ├── config/db.js          Mongo connection
│   ├── models/
│   │   ├── User.js           handle, cached platform stats, rating history
│   │   └── Rivalry.js        pairs two users, stores obsession scores + narrative log
│   ├── services/
│   │   ├── codeforces.js     CF public API — rating, history, submissions
│   │   └── obsessionScore.js composite metric: velocity + streak

How I Built It

Stack: MERN — React + Vite + TS on the frontend, Express + MongoDB on the backend, deployed on Vercel + Render.

Every stat comes straight from the Codeforces public API — I compute streaks, upsolve ratio, a LeetCode-style Easy/Medium/Hard breakdown, and strength/weak-spot tags directly from real submission data, not just cached totals.

One fun bug: my weekly-round tracking kept showing 0 progress even after solving problems, because I was computing day boundaries in UTC instead of IST — any solve before 5:30am IST landed on the "wrong side" of midnight from my own calendar's view. Fixed by shifting all boundary math into IST first.

Gemini is called directly (not templated) on every "Generate recap" — it reads live stats and returns structured JSON with a recap + a specific tip, grounded strictly in the real numbers to avoid hallucinated details.

Design: dark editorial theme, exactly two accents — amber for "you," ember for "them" — used consistently across every chart and card, so you can track the rivalry by color alone.

Prize Categories

Best Use of Google AI ✅ — Gemini is the narrative engine, not decoration. It reads each duel's live stats and writes a grounded recap plus a targeted catch-up tip for whoever's behind, every time.

Top comments (0)