ChronoFocus came from a small gap in my own routine. I’d be surprised by how far through the year we were, and in the moment there was no easy way to see it. I didn’t want a productivity system or a planner. Just a reminder of where I was in the year, every time I opened a new tab.
That’s the whole product: the percentage of the year that’s gone, the current week, the weeks left, and a progress bar. No settings, no accounts, no data entry.
Making the Number Defensible
The hard part of a “year progress” display isn’t the display. It’s agreeing with yourself on what the number means, so the bar doesn’t jump backwards or skip ahead.
I pinned everything to UTC. Time zones and daylight saving edge cases disappear when there’s a single reference frame. The year runs from the first instant of January 1 to the first instant of the next January 1. Week numbers follow what the user sees on their calendar, even when ISO rules get opinionated.
The core calculation:
function getYearProgress(now: Date): number {
const year = now.getUTCFullYear();
const start = Date.UTC(year, 0, 1);
const end = Date.UTC(year + 1, 0, 1);
const current = now.getTime();
const ratio = (current - start) / (end - start);
return Math.min(1, Math.max(0, ratio));
}
In the actual code this sits alongside week calculations and message selection, but the idea is the same. The goal is numbers that are boringly correct.
One Bar, One Badge
The UI is a horizontal bar for the year, a fill showing the current percentage, and a small badge riding the fill with the same number. Above it, a line of text: “This year is X% over.” Below, the current week and the weeks remaining.
On each update the extension recalculates the percentage and week, updates the text, adjusts the fill width, and moves the badge along the bar. The fill and badge ease toward new values over a short duration instead of snapping. It’s an animation you only notice if you close your laptop for a week and open a new tab, but without it the jumps feel jarring.
The layout is a single centered column. That sounds trivial. It also means the design stays readable on narrow and wide screens without a pile of layout rules.
No Framework, No Dependencies
Under the hood this is a plain browser extension. The new tab page is static assets plus a bit of JavaScript that reads the clock, computes the derived values, and applies them to the DOM and animation hooks.
No frontend framework, no runtime dependencies. A small build script minifies the source files and copies what’s needed into a distribution folder the browser loads as an unpacked extension. There are no network calls on the new tab screen; everything is computed locally, with a simple interval keeping the numbers fresh if the tab stays open.
The constraint I kept coming back to was trust. Fewer moving parts, fewer ways for the displayed percentage to be wrong.
The Look
Dark gradient background, centered column. The main percentage uses a display serif; supporting text uses a clean UI font. The bar has rounded corners and a subtle glow, and the badge reads like a small card resting on the fill.
Design tokens for colors, font sizes, spacing, and shadows live in CSS variables. The stylesheet stays short, and a future light theme would mostly be a matter of updating a few variables.
Accessibility comes from small choices: visible focus outlines, a font‑loading strategy that doesn’t hide text, motion that’s present but not aggressive. The page is mostly text and one bar. The job is to stay out of its way.
Most people who install it just notice a number and a bar inching across the year. That’s the product. The occasional raised eyebrow when the percentage is higher than expected comes free.