nextContest: The Chrome Extension That Turns Contest Tracking Into a Reminder Engine
A small but sharp browser tool for competitive programmers, built around persistent local state, background alarms, and a dedicated reminder window that appears exactly when a pinned contest is about to start.
- nextContest is built around intervention, not aggregation, because its core move is to surface a dedicated reminder window at the exact moment a pinned contest is close to starting.
- The repo keeps the extension coherent by treating chrome.storage.local as the persistent source of truth and React as a thin view layer on top of it.
- Its background worker is the real product, with alarms, retries, and listener safeguards doing the work that makes the reminder flow dependable.
- Manual contest entry broadens the tool beyond public APIs, so the same workflow can cover mock contests, university events, and anything else a programmer wants to track.
Most contest trackers stop at the list. nextContest goes one step further: it tries to own the last five minutes before a contest begins. That is the interesting design choice here, because it turns a Chrome extension into a timing system, not just a dashboard.
Hello guys, I made this extension nextContest - Contest Tracker in february this year, it is available on chrome web store. After getting some feedback to create a popup to remind pinned contest. I have finally added that feature
Why this extension is more than a contest list
The repo’s user-facing promise is simple. It tracks upcoming and live contests across platforms such as Codeforces, LeetCode, and CodeChef. The product’s sharper idea is that tracking only matters if it changes what happens when the clock is almost out.
That is why the reminder window matters so much. A badge or toast can be ignored. A dedicated reminder.html window created by the background worker is harder to miss, and it makes the extension feel intentionally present at the exact moment the user needs it.
The workflow behind the surprise
The architecture is cleaner than it first looks. A background service worker handles alarms and fetches. The popup reads from persistent storage. Manual contests join the same data set as fetched contests, so the UI stays simple even as the sources expand.
The background worker is the real product
In src/background.js, the extension defines two rhythms. contestFetch syncs contest data on a longer interval and retries if the network fails. remindContest checks every minute whether a pinned contest is within the five-minute warning window.
That separation matters. Fetching is about freshness. Reminding is about timing. The code also defends against a classic Manifest V3 problem by preventing duplicate alarm listener registration when the service worker restarts.
// Conceptual shape of the worker logic
chrome.alarms.create('contestFetch', { periodInMinutes: 45 });
chrome.alarms.create('remindContest', { periodInMinutes: 1 });
chrome.alarms.onAlarm.addListener(async (alarm) => {
if (alarm.name === 'contestFetch') {
// fetch contests, retry on failure
}
if (alarm.name === 'remindContest') {
// if pinned contest starts within 5 minutes, open reminder.html
chrome.windows.create({ url: 'reminder.html', type: 'popup' });
}
});
The key design move is not just the alarms. It is the choice to open a separate reminder window instead of relying on a passive notification. That gives the project a stronger surface for showing the contest name, platform, and urgency without forcing the user back into the popup.
Manual contests make the tool feel personal
The manual contest flow is small, but it changes the product shape. It lets users add mock contests, university events, or any event that will never appear in a public API. That makes the extension useful even when the broader contest ecosystem is incomplete.
It also keeps the repo honest about its audience. Competitive programmers do not only need official platform listings. They need a place to track whatever is actually on their calendar, and the extension’s data model is flexible enough to support that without special casing.
Why the state model stays simple
The repo avoids heavyweight state machinery. chrome.storage.local acts as the persistent source of truth, and the React layer reads and renders from it. That keeps the extension resilient across popup closes, service worker restarts, and browser sessions.
The advantage is architectural, not just stylistic. Because the storage layer is shared, the popup and background worker can coordinate without a more elaborate client state system. The code reads like a disciplined extension, not a mini web app trying to impersonate one.
| Project | Surface | Reminder style | Manual contests | Best for |
|---|---|---|---|---|
| nextContest | Chrome extension | Dedicated reminder window | Yes | Browser-native contest tracking with high-signal reminders |
| clist.by | Web app | Calendar and site-based reminders | Limited | Broad contest aggregation and API depth |
| Coder's Calendar | App plus extension | Calendar-oriented alerts | Varies | Cross-platform users who want calendar integration |
| Telegram bots | Messaging workflow | Chat notifications | Usually no | Users who want push reminders outside the browser |
How it compares to broader trackers
Compared with clist.by, nextContest gives up breadth and ecosystem depth. Compared with Coder's Calendar, it gives up some cross-platform reach. Compared with Telegram bots, it gives up the convenience of an inbox-style alert stream.
What it gains is immediacy. It lives in the browser, keeps the UI calm, and uses a dedicated reminder window to make the final nudge feel deliberate instead of noisy.
What this repo shows about modern extension design
The useful lesson here is that a good extension is not just a popup. It is a coordinated system of storage, alarms, background logic, and focused UI surfaces. nextContest makes that coordination feel lightweight, which is exactly why it works.
It is also a good example of product thinking at small scale. The repo does not chase every contest platform or every notification channel. It chooses one moment to own, then builds enough machinery to make that moment reliable.