Skip to content

feat: Implement Pomodoro Timer with reliable background audio#2

Open
NeshJesse wants to merge 1 commit into
AkongaLabs:mainfrom
NeshJesse:pomodoro-timer-solution
Open

feat: Implement Pomodoro Timer with reliable background audio#2
NeshJesse wants to merge 1 commit into
AkongaLabs:mainfrom
NeshJesse:pomodoro-timer-solution

Conversation

@NeshJesse

@NeshJesse NeshJesse commented Jun 23, 2025

Copy link
Copy Markdown

Bounty Solution Submission

Problem Statement

This bounty solves the challenge of creating a reliable Pomodoro timer web application with the critical requirement of background audio notifications that work even when the Chrome browser tab is minimized or in the background. The main technical challenge was overcoming Chrome's autoplay policies and background tab throttling to ensure consistent audio notifications during focus sessions.

Solution Approach

I implemented a single-file HTML application using Web Audio API instead of traditional HTML5 audio for superior background reliability. Key technical decisions included:

  • Web Audio API: Programmatically generated chime sounds for zero external dependencies
  • Absolute Timing System: Using Date.now() timestamps to prevent timing drift during background tab throttling
  • Dual Permission System: Integrating both Web Audio API and Notifications API for comprehensive browser permission handling
  • Glassmorphism UI: Modern, accessible design with comprehensive input validation
  • Progressive Enhancement: Graceful degradation when permissions are denied

Technical Implementation

  • Package Manager: N/A - Single HTML file with embedded CSS/JS (no build process required)
  • Database Setup: N/A - No database required for this client-side application
  • Environment Variables: N/A - Fully self-contained application
  • Build Process: N/A - Ready-to-use single HTML file

Testing Evidence

  • Test Coverage:

    • Background audio functionality with tab switching
    • Browser permission request flow (allow/deny scenarios)
    • Input validation (negative numbers, zero, large values, non-numeric)
    • Keyboard accessibility (spacebar controls, tab navigation)
    • Timer accuracy during background operation
    • Visual feedback and error handling
  • Test Results:

  • evidence via screenshots 'https://neshjesse.github.io/pomodoro/assets/exceed.png'

  • more evidence 'https://neshjesse.github.io/pomodoro/assets/decimalentry.png'

  • Critical Flows Tested:

    • User enables audio permissions → Browser prompt appears → Permission granted/denied
    • Set 1 minute timer → Switch to different tab → Audio notification plays at completion.Meets the criteria specified for (1-999)
    • Invalid input handling → Clear error messages displayed
    • Timer pause/resume functionality during active sessions
    • Accessibility flow using keyboard-only navigation
  • Test Results: All core functionality verified working in Chrome desktop. Background audio notifications trigger reliably when tab is inactive, which was the primary technical challenge.

Demo Evidence

  • Live Demo: The application runs entirely client-side from a single HTML file. Deployed on github pages
  • simply open https://neshjesse.github.io/pomodoro/

Setup Instructions

Step-by-step instructions to see how the code runs:

  1. Visit 'https://neshjesse.github.io/pomodoro/'
  2. Click "Enable Sound Notifications" button when prompted and confirm your machine is not muted and has a good volume precentage
  3. Allow permissions when Chrome shows the notification permission dialog
  4. Enter desired timer duration in minutes (1-999)
  5. Click "Start" to begin your focus session
  6. Switch to other tabs/applications - audio notification will play when timer completes

Database Setup

No database setup required - this is a client-side only application with no data persistence needs.

Architectural Decisions

1. Web Audio API over HTML5 Audio

  • Reason: Better reliability for background tab audio playback
  • Trade-off: Slightly more complex implementation, but critical for core requirement

2. Single HTML File Architecture

  • Reason: Meets requirement for no external dependencies
  • Trade-off: Larger file size, but easier deployment and distribution

3. Programmatic Sound Generation

  • Reason: Eliminates need for audio files, maintains zero dependencies
  • Trade-off: More complex audio code, but creates pleasant multi-harmonic chime

4. Absolute Timestamp Timing

  • Reason: Immune to Chrome's background tab throttling
  • Trade-off: Slightly more complex calculations, but ensures accuracy

5. Dual Notification System

  • Reason: Audio + browser notifications provide redundancy
  • Trade-off: More permission complexity, but better user experience

Bun/Yarn Justification

Package manager not applicable - this solution uses vanilla HTML/CSS/JavaScript with no build process, dependencies, or compilation step required. The single-file architecture meets the bounty requirement for minimal external dependencies while ensuring maximum compatibility and ease of deployment.


Pre-submission Checklist:

  • All bounty requirements met
  • Tests written and passing
  • Working demo available
  • Code is self-explanatory
  • Setup instructions complete
  • @adrianmurage tagged for review

I confirm this submission meets all requirements and is ready for review. @adrianmurage

Summary by CodeRabbit

  • New Features

    • Introduced a fully functional Pomodoro timer web application with customizable duration, start/pause/resume controls, and a large digital display.
    • Added audio and browser notification support upon timer completion, including permission handling and custom sound generation.
    • Implemented accessibility enhancements such as ARIA labels, keyboard controls, and dynamic status messages.
    • Ensured accurate timing even when the tab is inactive and provided user warnings before leaving the page.
  • Documentation

    • Added detailed notes on browser compatibility, performance considerations, and resource usage for the timer application.

- Complete HTML/CSS/JS implementation in single file
- Web Audio API for reliable background notifications
- Comprehensive permission handling with browser prompts
- Accurate background timing immune to tab throttling
- Full accessibility support and error handling
- Addresses Issue AkongaLabs#1 requirements completely
@coderabbitai

coderabbitai Bot commented Jun 23, 2025

Copy link
Copy Markdown

Walkthrough

A new single-file Pomodoro timer web application was introduced, implemented in HTML, CSS, and JavaScript. The app features accurate timer logic, custom audio and browser notifications, robust permission handling, accessibility enhancements, dynamic UI feedback, and modern responsive design. Documentation on browser-specific behaviors and performance considerations was also added.

Changes

File(s) Change Summary
index.html, codesumm.md Added a complete, standalone Pomodoro timer web app with timer logic, notifications, accessibility, and modern UI.
notes.md Added documentation on Chrome-specific limitations, optimizations, and resource usage for the timer app.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant UI
    participant TimerLogic
    participant Audio
    participant Notifications

    User->>UI: Set duration/start/pause/resume
    UI->>TimerLogic: Start or pause timer
    TimerLogic->>UI: Update display/status
    TimerLogic-->>Audio: On completion, play beep
    TimerLogic-->>Notifications: On completion, show browser notification
    Notifications->>User: Display notification
    Audio->>User: Play sound
    User->>UI: Interact (e.g., close notification, focus window)
Loading

Possibly related issues

Poem

A Pomodoro tick and a Pomodoro tock,
With beeps and alerts to beat the clock.
Minutes march on, the colors glow bright,
Accessible, modern, and coded just right.
Take a break, dear friend, when the timer is done—
The rabbit’s web timer keeps work and fun!
🥕⏲️


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (7)
notes.md (1)

23-23: Add missing punctuation
The bullet “Generated audio: No audio file loading overhead” should end with a period for consistency.

index.html (6)

5-5: Duplicate viewport meta tags
There are two <meta name="viewport"> declarations at lines 5 and 18. Consolidate these into a single tag (e.g., include maximum-scale=1.0, user-scalable=no in one).

Also applies to: 18-18


272-275: Prefer keydown over keypress
The 'keypress' event is deprecated for modern browsers. Switch to minutesInput.addEventListener('keydown', ...) for the Enter key to ensure better compatibility.


400-403: Specify radix in parseInt
Use parseInt(minutesInput.value, 10) to avoid potential octal parsing issues in legacy environments.


444-446: Unused expectedEndTime
The property timerState.expectedEndTime is set but never read. Remove it or update updateTimer() to use expectedEndTime for more direct remaining-time calculation.


289-296: Await testContext.close()
testContext.close() returns a Promise that isn’t awaited. Consider using await testContext.close() (inside an async block) or handle the promise to ensure the context is properly closed.


375-388: Normalize indentation
The playNotificationSound function has inconsistent indentation, making it harder to read. Align all lines with the surrounding code block’s style.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 086b69e and 33a64f3.

⛔ Files ignored due to path filters (5)
  • assets/decimalentry.png is excluded by !**/*.png
  • assets/exceed.png is excluded by !**/*.png
  • assets/favicon.ico is excluded by !**/*.ico
  • assets/favicon.jpeg is excluded by !**/*.jpeg
  • assets/screenshot.png is excluded by !**/*.png
📒 Files selected for processing (3)
  • codesumm.md (1 hunks)
  • index.html (1 hunks)
  • notes.md (1 hunks)

Comment thread notes.md
Comment on lines +9 to +11
- **Cross-browser compatibility**: Optimized specifically for Chrome as requested
- **Mobile considerations**: Desktop-focused implementation
- **Network dependency**: None (fully self-contained)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Documentation misstates network dependencies
The note “Network dependency: None (fully self-contained)” contradicts the implementation, which loads Google Fonts and external assets. Please update this limitation to reflect the real external network dependencies (e.g., Google Fonts, favicon downloads).

🤖 Prompt for AI Agents
In notes.md around lines 9 to 11, the documentation incorrectly states there is
no network dependency, but the implementation loads external assets like Google
Fonts and favicons. Update the note to accurately reflect these external network
dependencies by mentioning Google Fonts and favicon downloads as required
external resources.

Comment thread codesumm.md
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pomodoro Timer</title>
<script src="index.js" defer></script>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Incorrect code snippet/reference
This file references an external <script src="index.js"> and shows raw HTML without markdown fencing. There is no index.js in the PR; the main script is embedded inline in index.html. Please update or remove the snippet, wrap examples in proper markdown code fences, and ensure the summary aligns with the actual structure.

🤖 Prompt for AI Agents
In codesumm.md at line 7, the snippet incorrectly references an external script
"index.js" which does not exist in the PR; the main script is inline in
index.html. Remove or update this reference to reflect the actual inline script
usage, wrap all code examples in proper markdown code fences for clarity, and
revise the summary to accurately describe the current file structure and script
inclusion.

Comment thread index.html
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pomodoro Timer</title>
<link rel="icon" href="assets/favicon.ico" type="image/x-icon">

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Favicon MIME type mismatch
The links for favicon.jpeg use type="image/png", which conflicts with the .jpeg extension—and you also declare a separate .ico icon. Please standardize your favicons. For example:

- <link rel="icon" type="image/png" sizes="32x32" href="assets/favicon.jpeg">
- <link rel="icon" type="image/png" sizes="16x16" href="assets/favicon.jpeg">
+ <link rel="icon" type="image/jpeg" sizes="32x32" href="assets/favicon.jpeg">
+ <link rel="icon" type="image/jpeg" sizes="16x16" href="assets/favicon.jpeg">

Also applies to: 24-25

🤖 Prompt for AI Agents
In index.html at lines 7 and 24-25, the favicon links have a MIME type mismatch
where a .jpeg file is declared with type="image/png" and there is also a
separate .ico icon declared. To fix this, ensure the href file extension matches
the declared MIME type for each favicon link, and standardize on one favicon
format (preferably .ico) by updating the href and type attributes accordingly.

@adrianmurage
adrianmurage self-requested a review June 23, 2025 04:29
@adrianmurage

Copy link
Copy Markdown
Member

@NeshJesse You were expected to use the github "request for review to tag me."
But given that this is the very first PR. I did it for you and will be lenient.

In future submissions. That lack of attention to detail is enough to render your submission null and void.

@adrianmurage adrianmurage linked an issue Jun 23, 2025 that may be closed by this pull request
@NeshJesse

NeshJesse commented Jun 23, 2025 via email

Copy link
Copy Markdown
Author

@adrianmurage

Copy link
Copy Markdown
Member

Turns out running a company takes a lot more than I anticipated. I apologize for not reviewing your work in the promised timeline. I assure you I haven't ignored or forgotten you. Founder duties to the company that is making all this possible have simply taken the # 1 priority. Because if the company fails, this program cannot exist. Thank you for understanding and I'll get back to you as soon as I possibly can.

@NeshJesse

Copy link
Copy Markdown
Author

Days turned to years it seems

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.

Pomodoro Timer Prototype - Development Instructions

2 participants