A small floating timer for whiz.study practice questions. whiz.study doesn't have a built-in timer, so Timer Buddy adds one: drag it anywhere on the page, pause and resume it, and it resets automatically for each new question. A toolbar popup and an on-page progress panel both show how long each question took.
A friend deleted my OnePrep account, so I moved my SAT/ACT practice over to whiz.study which, it turns out, has no timer. This exists to fix that.
- Floating widget — small, draggable, stays fixed on screen; remembers its position per site.
- Pause / resume without losing the running time.
- Automatic reset per question, layered across several signals so it holds up across different navigation patterns:
- a direct click on a Next/Continue/Submit-style button
- SPA route changes (
pushState/replaceState/popstate) - in-place DOM content swaps
- native
<select>question pickers - a manual reset button on the widget as a guaranteed fallback
- On-page progress popover — a small icon on the widget opens a live per-question bar chart for the current session, no need to open the toolbar popup.
- Toolbar popup — live elapsed time, a 7-day history chart (so you can see yesterday's average at a glance), and a per-question breakdown for the current session.
- Hover tooltips with exact timings on every bar, keyboard-focusable for accessibility.
- Runs in Chrome and Firefox from one codebase.
- Fully local — no backend, no network calls, no analytics. Everything lives in the browser's local extension storage.
Chrome / Edge / Brave
- Go to
chrome://extensions. - Enable "Developer mode" (top right).
- Click "Load unpacked" and select this folder.
Firefox
- Go to
about:debugging#/runtime/this-firefox. - Click "Load Temporary Add-on…" and select
manifest.jsonin this folder. - Firefox unloads temporary add-ons on restart, so reload it each session during development. A permanent install requires signing through Mozilla.
- No background script. The timer's state and ticking logic live entirely in the content script, computed from wall-clock timestamps rather than counting intervals, so elapsed time stays accurate even if the tab is throttled in the background. The popup reads persisted stats directly from storage and messages the active tab only for the live-running number.
- Shadow DOM. The widget renders inside an open shadow root so its styles can't leak into the host page and vice versa.
- Site-specific detection is isolated. Everything whiz.study-specific lives in
site-adapters/whizstudy.js. Its container/button selectors are currently generic heuristics (the real practice pages are behind a login wall) — the manual reset button always works regardless of how well auto-detection is tuned.
manifest.json MV3, permissions: storage + activeTab
content/
content.js timer state machine, auto-detect wiring, messaging
widget.js shadow-DOM widget UI, drag-to-reposition, progress popover
site-adapters/
whizstudy.js whiz.study-specific selectors and heuristics
lib/
browser-polyfill.js vendored mozilla/webextension-polyfill (MPL-2.0)
storage.js storage.local helpers (position, session log, daily stats)
chart-utils.js shared bar-chart rendering used by the popup and the widget
popup/
popup.html / popup.js / popup.css
icons/ stopwatch icons
- Question-container detection in
site-adapters/whizstudy.jsruns on generic guessed selectors rather than whiz.study's real markup. To sharpen it: inspect the question container and the Next/Continue button on a live practice page, then put the exact selector first inquestionContainerSelectors/nextButtonSelectors— no other file needs to change. browser_specific_settings.gecko.idinmanifest.jsonis a placeholder; replace it with a real identifier before publishing to Firefox's add-on store.
Bundles mozilla/webextension-polyfill (MPL-2.0) for a single browser.*-based codebase across Chrome and Firefox.
MIT — see LICENSE.