<aside> ๐Ÿ”

At a glance

A tool is only as honest as the words it uses to describe itself.

Overview

Kairos is a freelance time tracker I built and deployed for my own daily use: a live timer, manual backfill, editable entries, per-client color-coding, at-a-glance weekly and monthly totals, a PDF time export grouped by project and task with pie charts, and JSON backup/restore. It runs entirely in the browser, stores everything locally, and installs to my dock and phone like a native app.

But the reason it belongs in a content design portfolio is that building software surfaced the same instincts I bring to writing: noticing when a word is doing the wrong job, cutting what doesn't serve the person, and naming a thing so its purpose is legible at a glance. This case study tells that story, including a mistake I made, and what it taught me about attention.

<aside> ๐Ÿ“Œ

Vibecoded, then shipped for real. I built this conversationally, feature by feature, then deployed it as a standalone app on Vercel. Everything below (the timer, the export, the naming, the deployment) is the actual build, not a mockup.

</aside>


The challenge

I invoice international clients in EUR and USD, across projects that each take a different amount of time. I wanted something like Clockify, but shaped to how I actually work, not a generic tool I'd bend myself around. That meant deciding, at every step, what earned its place and what was scaffolding I'd eventually tear out.

Two pressures ran underneath the whole build:


The miss, and the discipline of noticing

Halfway through, the app synced entries into a Notion database. When I later decided to strip Notion out and make Kairos fully self-contained, I rewrote the sync code, removed the integration, and moved on.

Except I didn't remove all of it. The empty-state message, the very first thing a new user reads, still said:

"Nothing tracked yet. Start the clock and your first entry lands here โ€” and in Notion."

The app no longer touched Notion. The sentence promised something the product could no longer do. It was live on the deployed site before I caught it.

That's a small bug in code terms. In content terms it's the whole game: a piece of copy making a promise the product doesn't keep. It's exactly the failure I'm hired to prevent in other people's products, and I'd shipped it in my own. The fix was one line. The lesson was the reminder that removing a feature isn't done when the code compiles; it's done when every word about that feature is gone too. Copy is part of the system, not a layer on top of it.

I keep this in the case study on purpose. The instinct that eventually caught it (reading the interface as a reader, not a builder) is the same instinct the whole craft rests on.