Interval Timer
A mobile-first interval training timer that installs as a Progressive Web App. No build step, no dependencies, no network calls — just static files.
The cycle
For every set, each exercise gets a pause followed by a training block:
for each set:
for each exercise:
pause (default 15s) text is grey
training (default 45s) text turns red
- Start rings a bell, shows the first exercise in grey and runs the pause.
- When the pause ends a beep plays and the text turns red for the training block.
- When training ends another beep plays, the next exercise appears and its pause begins.
- After the last exercise of the last set, a triple bell rings and the screen shows Workout complete.
Pause / Resume freezes the clock; Reset returns to the start. The screen is kept
awake during a session via the Screen Wake Lock API.
Files
| Path | Purpose |
|---|---|
index.html |
Markup: stage, controls, settings |
styles.css |
Dark theme; grey/red phase colours |
app.js |
Timer state machine, Web Audio bell/beep, exercise list |
manifest.webmanifest |
PWA metadata and icons |
sw.js |
Service worker — app shell cached for offline use |
icons/ |
Generated app icons |
tools/make_icons.py |
Regenerates the icons (needs Pillow) |
tools/smoke_test.mjs |
Headless-Chrome test of the whole cycle |
start |
Your local live-server launcher (port 8080) |
Settings and the exercise list are stored in localStorage, so they survive a reload.
Running it on your phone
PWA installation and offline caching require a secure context (HTTPS, or
localhost). A plain http://<laptop-ip>:8080 URL works as a normal web page but
will not be installable and will not cache offline.
1. Serve the files
cd timer
python3 -m http.server 8080
# or, using the ./start script (Node + live-server, auto-reload)
./start
2. Give your phone an HTTPS URL
Either expose the local server through a tunnel, for example:
cloudflared tunnel --url http://localhost:8080
# or: npx localtunnel --port 8080
or upload the folder as-is to any static host (GitHub Pages, Netlify, Cloudflare Pages, Vercel). There is nothing to compile.
3. Install
Open the HTTPS URL on the phone and use Add to Home Screen (Safari: Share menu; Chrome: banner or the ⋮ menu → Install app). It then launches fullscreen and works offline.
Audio notes
- The bell and beeps are synthesised with the Web Audio API, so there are no sound files to download and they work offline.
- Audio is unlocked by the first tap on Start, as mobile browsers require.
- On iOS the ringer/silent switch still mutes Web Audio playback — turn silent mode off for a workout.
Tests
With a server on 127.0.0.1:8765 and Chrome running with --remote-debugging-port=9222:
cd timer
node tools/smoke_test.mjs
The test drives the real page and asserts the exact pause/training sequence for 2 sets × 3 exercises, the grey→red colour switch, phase durations, the frozen clock while paused, reset/restart behaviour and settings persistence.