// Build Note
A focus companion that lives in your Chrome side panel.
TIMELINE
2 months on and off, incl. Chrome Store submission and review
STACK
Vanilla JS · Custom state machine · Chrome Extension APIs · Claude Code · Codex
STATUS
Live, and napping well
Where it started
Too many tabs, too little memory
Puff began with a question: how do you hold one small intention without adding pressure, noise, or another list to manage?
When I’m deep in focused work, jumping between tabs and research rabbit holes, I lose track of time and forget about basic self-care, including the small breaks I meant to take. Most reminder tools assume you want a planner or task system. But a big task list can become visual evidence of failure, not a useful plan, and notifications feel loud, demanding, and easy to dismiss.
I wanted to try removing scanning, prioritizing, and guilt by design. Not "help you get more done," just help you hold one fragile intention without losing it.
What it Became
One thing, held gently
Puff asks for one thing to remember. You tell it, choose when, and set the reminder. Then Puff goes to sleep with it.
Puff stays in the side panel while you work, on whatever page you're on. When it's time, Puff doesn't buzz or badge. It wakes up with a little bounce and shows you the one thing.
Tell it you did it and Puff celebrates. Tell it not yet and Puff waits. Neither answer costs you anything. No list builds up and there's no guilt.
It's quiet on purpose, a small tool built more for myself and anyone who finds it useful than for scale.

The judgment calls
Getting Puff to feel like someone
I worked with Claude Code and Codex throughout. The reminder logic was only part of the work. I also had to decide how Puff would stay present, how it would wait, and what would make its reactions feel like behavior rather than a repeating animation.
#1
Choosing presence over interruption
Early on, Claude asked whether Puff should be a quick popup you glance at or something that stays visible. A popup felt too easy to lose. A separate floating window felt like another thing to manage.
After digging into the Chrome extension docs, I chose the side panel. Puff could sit beside the page I was already using, without needing its own window.
A task or intention can disappear the moment your attention shifts. Keeping the reminder beside my actual browser tab meant I didn’t have to remember to check somewhere else. I didn’t want a list to scan or another surface to manage. I wanted the thing I’d already decided mattered to stay beside me while my attention moved around.
Puff needed to be noticeable when it woke up, but calm enough to live beside my work the rest of the time. That balance mattered more than making the reminder louder.
#2
From looped animation to a character
Codex’s first pass at Puff’s facial animation was the fast, easy version: two or three expressions cycling on repeat. It worked technically, but Puff felt like a looped GIF, not a character.
I redirected the approach. Instead of one fixed cycle, I wanted individual expression clips that could combine like Lego pieces, with enough variation in sequencing and timing that the repetition wouldn’t be obvious.
This was my first Chrome extension, so I was learning the platform while figuring out the character. I split the work into two parallel tracks so I could work on each separately.
Track A → The shell
I started with a blank side panel that opened. Nothing else yet. I got the manifest, permissions, and plumbing working cleanly first, then built out the four reminder states: Awake, Nap, Remind, and Done.
That gave me a working structure for the reminder before bringing the animation into it.
Track B → The animation
I started with a face study, expanding the original loop’s two or three expressions into a whole collection of individual clips. I worked on each expression in isolation, from blinks and winks to eye rolls and cheeky faces. Each one had to feel right on its own before becoming part of a sequence.
Then I built a separate sandbox for sequencing. The number of clips could vary: a shorter mix for a quick moment, a longer one when Puff had more time to react. I tuned the transitions so the clips could mix and match cleanly, rather than only working in a few preset sequences.
I checked the whole scene, too: where Puff sat relative to the sea, how active the waves were, and what the background mood felt like. The face wasn’t the only thing setting the tone.
Once the states held up on their own and the sequences felt right, I merged the animation into the shell. That was the moment the extension stopped being a blank panel and started being Puff.
Process
No Figma until the end
I worked out Puff’s interactions and personality in code, testing and tuning the version as I went.
Chat with Claude to shape the concept → Build the shell and animation tracks with Codex and Claude Code → Tune until Puff felt right
I didn’t open Figma until the very end, to make screenshots for the Chrome Web Store submission. Most of the design work happened in the running extension and animation sandbox, where I could watch the timing, try different sequences, and see Puff beside an actual browser page.
The workflow looks simple written out, but there was a lot of tuning inside that loop. I wasn’t just checking whether the reminder worked or the animation played correctly. I was tuning how Puff waited, woke up, and celebrated until those moments felt right for a quiet companion.
What I learned is that spotting an opportunity to use AI is only half the job. The harder, more valuable part is staying patient enough to keep refining what it hands you instead of accepting the first version that technically works.
That’s the instinct I trust most now: moving fast, but noticing when fast and right aren’t quite the same thing.
