Pomodoro Timer
A timer that proves on screen why setInterval is not a clock.
- JavaScript
- SVG
- Web Audio
- HTML
About this project
A 25/5/15 pomodoro timer with a circular SVG progress ring, configurable lengths, a session counter, and an end-of-session chime synthesised in the browser rather than loaded from a sound file.
It is built around the most common bug in beginner timer projects: setInterval(fn, 1000) does not promise to run fn every second, only that it will not run any sooner. The real gap stretches with whatever else the page is doing, and a backgrounded tab is throttled deliberately. Every tick that assumes exactly one second passed loses whatever extra time actually elapsed, permanently, and always in the same direction.
The fix is not a smaller interval or a correction factor — it is to stop counting and derive every reading from one absolute timestamp. To prove the point, this timer runs a deliberately naive counter alongside the real one and shows you both, along with the longest gap the browser actually left between ticks. Hide the tab for a minute and come back to see the difference.
What you will learn
- Understand why setInterval drifts, and why the drift only ever runs one way
- Derive a countdown from an absolute target timestamp instead of decrementing a counter
- Animate an SVG progress ring with stroke-dasharray, with no library
- Synthesise a sound with the Web Audio API rather than shipping an audio file
- Validate user input by writing the corrected value back, so the screen never disagrees with the program
Before you start
- JavaScript basics — functions, events and setInterval
- A browser and a text editor. Nothing to install.
New to JavaScript? The free JavaScript course covers everything this project assumes.
Academic integrity notice
These projects are provided for learning, experimentation and reference. Understand the code, modify it for your own requirements, and acknowledge external work according to your institution’s academic policies. Priodemy does not supply work to be submitted as your own.
Features
- Countdown derived from a target timestamp, so it stays correct through throttling and background tabs
- A naive counter running alongside it, with the drift and the longest observed tick gap shown live
- Circular SVG progress ring, no library
- End-of-session chime synthesised with the Web Audio API — no audio file to ship
- Configurable focus, short break, long break and long-break interval, with input corrected on screen
- Keyboard shortcuts, session counter, and a countdown that does not spam screen readers
Technology stack
Track: Web Development · Level: Starter
What is included
- index.html, style.css and script.js — commented throughout
- A README on timer drift, with the experiment to run and an honest note on what the on-screen figure does and does not prove
- Suggested extensions, including a task list and a completed-sessions log
Delivered as a 18 KB ZIP. SHA-256 published under Changelog so you can verify it.
System requirements
- Operating system
- Any
- Runtime
- Any modern browser. No install, no build step.
Licence
Learn from it, change it, and use it in your own coursework and personal projects. Do not resell it or pass it off as your own original work.
- Personal and educational use
- Modifying the code however you like
- Using it as the basis of your own coursework, with honest acknowledgement
- Putting your modified version in a portfolio or on your own GitHub
- Reselling or redistributing the project, modified or not
- Presenting it as your own original work
- Commercial deployment — see the Commercial licence
Support window: 6 months from download.
Frequently asked
Why does the timer keep a second, deliberately wrong counter?
Because drift is invisible in a screenshot and easy to disbelieve. Running the wrong implementation next to the right one, and showing the gap between them, turns the lesson into something you can watch happen. Hide the tab for a minute and come back.
Will the chime fire if the tab is in the background?
Not necessarily at the exact moment, and the README says so rather than pretending otherwise. A throttled tab may run no code at the instant zero passes, so the chime can arrive late. The displayed time is still correct, because it is worked out from the target rather than counted.
Why synthesise the sound instead of shipping an MP3?
Because it keeps the project to four files with nothing fetched from anywhere, and because oscillators and gain envelopes are worth meeting. If the browser has no Web Audio support the button tells you it heard nothing, rather than claiming success.
Changelog
- First release
SHA-256d49bbcafc7ff5f588c4d2ec040001fec7287142885021bb97e4ddc13e436c598