Johan Alphonso Braga
WorkProjectsReadingStackCraftDesignStatusResume

Utilities

Ask anything

Elsewhere

GitHub

All projects

Tools / 2026 / Live in the browser

FocusForge

A focus timer that keeps time when you switch tabs, rings when time's up, and shows where your week went. Ember, a little spark mascot, keeps you company.

FocusForge

01

The problem

Browser focus timers fail in the tab you are not looking at. Chrome slows timers in hidden tabs to once a second and, after five minutes, to once a minute, so a timer that counts ticks runs long. Memory Saver can unload a background tab and reload it later with no warning, which wipes a timer held only in memory. A timer that ends silently in another tab goes unnoticed, and a session only counts if you remember to log it.

02

How I approached it

The timer is plain state plus pure functions with no DOM, so Node tests cover it. It counts down to a fixed end time and reads the clock on every tick and when the tab comes back, so throttling cannot stretch it. The state is saved whenever it changes and when the tab is hidden, as Chrome advises since no event fires before a discard, and on load a running timer keeps counting against its saved end time. A focus block that ran out while the page was closed is logged at the minute it really ended. The chime is Web Audio unlocked from the Start click, the tab title carries the time left, and the notification permission is asked for only from its own switch. Streaks and day totals use the local offset rather than UTC, so a 7am session in Manila lands on the right day.

03

The outcome

One Start/Pause button, Finish now that logs the minutes actually done, a progress ring, named sessions with recent names suggested as you type, and a 7 day breakdown by name next to today, this week and the streak. 23 tests with no dependencies cover the clock, save and restore (including a timer that ran out while closed), the tab title, local-day streaks and the per-name totals, on Node 20, 22 and 24 in CI.

04

The mascot

Ember is a spark drawn in inline SVG. Her face follows the timer: sleepy before the first session, eyes closed and quiet while you focus, worried when paused, happy on a break, and she throws sparks when a block is done. Her eyes follow the pointer, or the field you tap on a phone, and tapping her gives a tip for the moment you are in. What she says goes through an aria-live region, the x tucks her away, and she holds still under reduced motion.

focusforge.johanthegoat.xyz Open in a new tab ↗
Next projectUPCAT Reviewer →