Skip to content

feat(pomodoro): zero-dependency vanilla Pomodoro timer#3

Open
TheBeege wants to merge 1 commit into
mainfrom
feat/pomodoro-app
Open

feat(pomodoro): zero-dependency vanilla Pomodoro timer#3
TheBeege wants to merge 1 commit into
mainfrom
feat/pomodoro-app

Conversation

@TheBeege

Copy link
Copy Markdown
Member

What and why

Implements a self-contained Pomodoro timer web app as a set of three static files
(index.html, styles.css, app.js) with zero build tooling, zero runtime
dependencies, no CDN, and no external assets. The app opens directly via file:// and
works on any static server. Closes spec specs/2026-05-30-pomodoro-app.md.

Files changed

File Role
index.html Document structure, controls, ARIA live regions
styles.css Layout, interval theming via data-interval attribute, flash animation, focus styles
app.js All behavior: state model, drift-free ticker, controls, audio, visual cue
specs/2026-05-30-pomodoro-app.md Spec — status flipped to Delivered
plans/2026-05-30-pomodoro-app.md Implementation plan
adr/2026-05-30-vanilla-single-page-no-build.md ADR — Accepted
adr/2026-05-30-walltime-drift-free-countdown.md ADR — Accepted
adr/README.md Index updated with both new ADRs

Intentional interface / contract changes

Greenfield feature — no existing interfaces changed.

The three filenames and their relative co-location are the observable contract:
index.htmlstyles.css + app.js must stay siblings for file:// to work.

ADRs added

  • adr/2026-05-30-vanilla-single-page-no-build.md — Accepted: three sibling static files via classic <script defer>; no ES modules (blocked under file://), no bundler, no dependencies.
  • adr/2026-05-30-walltime-drift-free-countdown.md — Accepted: remaining time derived from endAtMs = Date.now() + remainingMs on each tick rather than accumulated from tick deltas, preventing cumulative drift under background-tab throttling.

Spec / plan

  • Spec: specs/2026-05-30-pomodoro-app.md
  • Plan: plans/2026-05-30-pomodoro-app.md

Quality gate results

  • node --check app.js — SYNTAX OK
  • grep -rIn -E "https?://|//cdn|fonts\\.|unpkg|jsdelivr|cdnjs" index.html styles.css app.js — NO EXTERNAL URLS FOUND
  • test ! -e node_modules — PASS (no node_modules)
  • test ! -e package-lock.json — PASS
  • No bundler configs present (no webpack/vite/rollup/babel configs)
  • No type="module" in any script tag
  • No localStorage, sessionStorage, Notification API usage
  • npx eslint — blocked by sandbox auto-mode policy; node --check (syntax gate) passed cleanly as the fallback per the plan

Test plan

  • Open index.html via file:// — displays 25:00, "Work", count 0, Start button
  • Press Start — counts down once per second; tab title updates
  • Press Pause — countdown freezes; press Resume — continues from same value
  • Rapid double-click Start, double-click Pause — no double-speed, no freeze corruption
  • Press Reset while running — returns to 25:00, stopped, count unchanged
  • Press Skip on Work — advances to Short Break, count NOT incremented
  • Let a Work interval reach 00:00 (fast-mode or wait) — count +1, beep + flash fire, Short Break loaded ready (not auto-started)
  • Complete 4 Work intervals — 4th completion loads Long Break (15:00)
  • After Long Break completes — Work interval loads, workSinceLongBreak resets
  • Reload from any state — returns to fresh 25:00/Work/0 state
  • DevTools Network tab — zero requests beyond the three local files
  • DevTools Application/Storage — no localStorage entries
  • Keyboard-only navigation — all buttons reachable and operable; focus ring visible
  • Screen reader — interval transitions announced via live region

🤖 Generated with Claude Code

Delivers the full Pomodoro timer web app per spec 2026-05-30-pomodoro-app.md.
Three static files (index.html, styles.css, app.js) work via file:// and any
static server with no build step, no CDN, and no runtime dependencies.

Key behaviors implemented:
- 25/5/15-minute Work/Short-Break/Long-Break cycle with Long Break every 4th work
- Start/Pause/Resume toggle, Reset (no cycle advance), Skip (no Pomodoro credit)
- Wall-clock-derived countdown (endAtMs reference) prevents cumulative drift
- End-of-interval: synthesized Web Audio beep + CSS flash animation; visual cue
  fires independently of audio so browser autoplay suppression is handled safely
- Completed-Pomodoro counter; no auto-start after transition (waits for Start)
- ARIA live region announces transitions; role="timer" on countdown; no color-only
  interval signaling; visible :focus-visible ring on all buttons
- No localStorage, no Notification API, no network requests

ADRs added:
- adr/2026-05-30-vanilla-single-page-no-build.md (Accepted)
- adr/2026-05-30-walltime-drift-free-countdown.md (Accepted)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant