Building a Countdown That Doesn't Lie: Background Tabs, Timer Drift and Web Audio Alerts
A countdown timer sounds like a ten-minute exercise: subtract one from a number every second and show it. Then you switch to another window for an hour of deep work, come back, and the timer says 12 minutes are left when
A countdown timer sounds like a ten-minute exercise: subtract one from a number every second and show it. Then you switch to another window for an hour of deep work, come back, and the timer says 12 minutes are left when it should have finished 20 minutes ago.
We built a free Focus Timer for long, uninterrupted work blocks, and the interesting engineering was all in making it behave when nobody is looking at the tab. Here is what we learned, with the tool as a worked example.
The tool in 30 seconds
A Pomodoro timer forces 25-minute rounds whether the work fits or not. Focus Timer is a single countdown, anywhere from 1 to 240 minutes.
- Six presets: 15, 30 and 45 minutes, and 1, 1.5 and 2 hours
- + and − steppers in 5-minute steps, locked while the timer runs so a stray tap can't reset your progress
- A progress ring, pause and resume, and a reset that doesn't clear your stats
- Two counters: Sessions completed and Total focus time
If you want breaks built in, we have a separate Pomodoro Timer.
Problem 1: a repeating timer is not a clock
The obvious way to build a countdown is to subtract one second every time a one-second timer fires. It breaks in two ways.
First, the timer drifts. Each tick fires slightly late, and those small delays add up over a long session. Second, browsers throttle timers in background tabs, so your tick may run far less often than once a second. A tab left hidden for an hour can fall badly behind.
The fix is to stop counting ticks and compare against the real clock instead. When the session starts, note the exact moment it should end. On every redraw, work out how much time is left by subtracting the current time from that end time. The timer then only decides when to redraw, and the answer always comes from the clock, so it stays correct no matter how late a callback runs.
That is the principle our timer follows. It counts against the clock rather than counting ticks, so it ends on time even when the tab is behind other windows.
Pausing needs one extra step: remember how much time was left when you paused, then calculate a fresh end time when you resume.
Problem 2: nobody is watching the tab
A deep-work timer is useless if the alert only works when the tab is in front. Focus Timer uses several signals at once:
- Sound, generated in the browser
- A flashing tab title, which shows in the tab strip even when you're elsewhere
- Vibration on phones
- An optional system notification, switched on with "Notify me in other tabs"
Sound without an audio file
Every sound is generated with the Web Audio API, so there are no audio files to download. You get a short tick in each of the final 5 seconds, and at 0:00 your chosen alert (Chime, Bell, Alarm or Soft) repeats for up to a minute, or until you click.
The autoplay rule
Browsers only let a page play sound after the user has interacted with it. A timer that someone starts and then ignores for 90 minutes can hit this wall. So the page has a Test sound button, and tells you to press it if you plan to leave the tab untouched. That first click unlocks audio for the rest of the session.
Notifications follow a similar consent model: the browser asks for permission first, which is why the system notification is opt-in.
Problem 3: counting what actually happened
The two stats follow deliberately strict rules:
- Sessions completed goes up only when the countdown reaches zero.
- Total focus time adds the full length of each completed session, however many times you paused it.
- A session you reset before 0:00 adds nothing. No partial credit.
This matters because a focus stat you can pad by tapping Reset is worthless, and one that punishes you for answering a quick message is demotivating. The rule we picked is "finished means finished."
Display is a small detail worth getting right: totals show as 1h 45m once you pass 60 minutes, not 105m.
One limitation to know about
The counters are not a long-term record. They live only for the current page session and reset when you close it. Treat them as a signal for today, not a database. If you want a permanent log, copy the numbers somewhere after a work block.
Why a single countdown beats a rigid cycle
Some tasks deserve 90 minutes of unbroken attention. Others are done in 12. Fixed 25-minute intervals interrupt the first kind and pad the second. A timer that accepts the length you actually need, with no built-in breaks, fits the work instead of imposing a structure on it.
Try it
Open the Focus Timer, pick a preset and start. It runs in your browser with no sign-up. The rest of the Productivity category includes a Task Prioritizer, Habit Tracker and Standup Notes.
How long is your ideal uninterrupted work block: 25 minutes, 90, or something else? Tell me in the comments.
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.