A lightweight interval training timer per the V1 PRD: configure work/rest durations and rounds, then run a color-coded, audio-cued workout loop.
Two versions live in this repo:
- Native iOS app (
IntervalTimer/) — requires a Mac with Xcode to install. - Progressive Web App (
docs/) — same features, zero cost, no Mac needed. Host it on GitHub Pages, open it in Safari, and "Add to Home Screen".
The web version in docs/ is a dependency-free single-page app (plain HTML/JS, no build step) that ports the iOS app one-to-one: the same warmup → work/rest → finish state machine, wall-clock timing, synthesized audio cues, phase-colored full-screen UI, and last-used-settings persistence.
- On GitHub: Settings → Pages → Build and deployment → Source Deploy from a branch, branch main, folder /docs → Save.
- After a minute the app is live at
https://<your-username>.github.io/interval-timer/.
To try it locally first: python3 -m http.server -d docs 8000 and open
http://localhost:8000.
- Open the GitHub Pages URL in Safari (must be Safari, not Chrome).
- Tap the Share button → Add to Home Screen → Add.
- Launch it from the home-screen icon — it opens full-screen with no browser chrome, works offline (service-worker cache), and never expires.
- Audio needs a tap first: iOS only unlocks web audio after a user gesture — the Start button handles this, so cues just work.
- Screen off / backgrounded: a web app cannot run in the background the way the native app's audio session can. The timer keeps the screen awake while running (Wake Lock API) and, if you do switch away, it fast-forwards to the correct phase when you come back — but cues won't sound while Safari is backgrounded, and there are no backup local notifications.
- Silent switch: web audio respects the ringer switch on iOS; flip the ringer on (or use volume buttons) to hear cues.
- A Mac with Xcode 16 or newer. iOS apps can only be compiled and installed onto an iPhone from macOS — this cannot be done from Linux/WSL.
- An Apple ID (a free one works; no paid developer account needed).
- iPhone 13 running iOS 17 or later, plus a USB cable for the first install.
- Copy this whole folder to your Mac and open
IntervalTimer.xcodeprojin Xcode. - Select the IntervalTimer target → Signing & Capabilities tab:
- Check Automatically manage signing.
- Under Team, sign in with your Apple ID and select the personal team.
- If Xcode complains the bundle ID is taken, change
com.seantestapp.IntervalTimerto anything unique.
- On your iPhone: Settings → Privacy & Security → Developer Mode → On (the phone restarts). This toggle only appears after step 4's first connection on some iOS versions — connect first if you don't see it.
- Connect the iPhone via cable, unlock it, and tap Trust This Computer.
- In Xcode's toolbar device picker, choose your iPhone, then press Run (⌘R).
- First launch on-device: Settings → General → VPN & Device Management → trust your developer certificate, then open the app again.
- Allow notifications when prompted (used for background transition alerts).
Free Apple ID note: apps signed with a free personal team expire after 7 days — just press Run again to reinstall. A paid developer account extends this to a year.
docs/ Web app (PWA), served by GitHub Pages
index.html Entire app: UI, state machine, engine, audio
manifest.webmanifest Install metadata (name, icons, standalone)
sw.js Service worker: offline cache
icon-180.png, icon-512.png Home-screen icons
IntervalTimer/
IntervalTimerApp.swift App entry point
Models/
WorkoutConfiguration.swift Work/rest/rounds + UserDefaults persistence
WorkoutSession.swift Pure phase state machine (UI-independent)
Engine/
WorkoutEngine.swift Wall-clock countdown, cue timing, lifecycle
Services/
AudioCueService.swift Synthesized tone cues via AVAudioEngine
NotificationScheduler.swift Local-notification backup for background
Views/
ConfigurationView.swift Setup screen
DurationPicker.swift Minutes/seconds wheel picker
ActiveTimerView.swift Full-screen workout UI
Info.plist Background audio mode, portrait-only, etc.
- Silent mode: the audio session uses the
.playbackcategory, so cues sound even with the ringer switch on silent. Background music (Spotify, Apple Music) is ducked for the duration of the workout, not stopped. - Background accuracy: timing is wall-clock based and the app keeps an
active audio session (with the
audiobackground mode) while a workout runs, so the countdown and cues continue with the screen off or the app minimized. Local notifications are also scheduled for every remaining transition as a backup, and cancelled when you return to the app. - Screen lock: auto-lock is disabled (
isIdleTimerDisabled) only while a workout is running, and restored when it ends or you exit. - Halfway cue: the work-interval double-beep fires only on work intervals of 10 seconds or longer, so it never collides with the 3-2-1 countdown.
- No rest after the final round — the last work interval goes straight to the finish chime.