I consider myself to be an expert procrastinator. Over the years, I’ve tried no shortage of tools and techniques to fix this problem. Pomodoro timers, distraction blockers, minimalist writing apps. Most of them are well-designed and do exactly what they claim. They help you track time and encourage focus. What they don’t do is enforce it.
Nearly all of these tools rely on the same assumption that once you start a timer, you’ll follow through. That you won’t open a new tab, check a notification, or drift into the “just one more” trap. In practice, it’s much harder. The moment your attention slips, the tool has no way to respond. So, instead of continuing to cycle through existing productivity tools, I decided to build the one feature I felt was missing.
A Pomodoro timer that enforces focus
It’s not just a timer anymore, rather a focus assistant
The concept is straightforward: a Pomodoro timer that doesn’t just measure focus sessions, but also controls how the browser behaves during them.
Rather than treating every session the same, the extension introduces different “focus levels.” Each level reflects how strict the session should be, and the browser responds accordingly. In a more relaxed mode, switching tabs might be allowed without restriction. In a stricter mode, the extension could warn you when you try to leave your current tab or prevent the action entirely.
I know how “big” my willpower is. So, the key idea is to shift the burden of discipline away from the moment of distraction. Instead of relying on willpower during the session, I make a decision upfront about how much flexibility I want, and the extension enforces that decision.
Defining the project scope
Mind mapping the features
One of the easiest mistakes to make with a project like this is overengineering it from the start. It would be simple to add features like usage analytics, cross-device syncing, or a more elaborate interface. Instead, I deliberately kept the scope narrow.
The goal for the first version is simply to validate the idea. That means focusing on a small set of core capabilities: a working Pomodoro timer, a way to select a focus level, the ability to detect tab switching, and basic enforcement of those rules. If those pieces work together reliably, the extension is already useful. Anything beyond that can be layered on later.
Vibe coding with Claude
My trusted programming buddy in action
Rather than writing the entire extension manually, I approached this as an experiment in AI-assisted development.
The workflow is intentionally simple. I break the project into small, clearly defined steps, then prompt Claude to generate the code for each part. After that, I run the code locally, test how it behaves, and make adjustments where necessary.
Starting with the basics
Before adding timers or focus rules, the first step is simply to get a Chrome extension running. That means setting up a valid manifest file, loading the extension in the browser, and confirming that it can display a basic interface. It’s a small step, but an important one. Once that foundation is in place, we can start layering in actual functionality.
To keep things predictable, I gave Claude a very specific prompt. Creating a well-crafted prompt is crucial knowledge for vibe coding.
Create a minimal Chrome extension using Manifest V3.
Requirements:
- Include a valid manifest.json file
- Add a simple popup UI (popup.html)
- The popup should display a title: "Pomodoro Tab"
- Include a short placeholder text below the title: "Extension loaded successfully"
- Keep the structure simple and clean
- No external libraries or frameworks
- Use plain HTML, CSS, and JavaScript only
- Organize files clearly (manifest.json, popup.html, optional popup.js)
Make sure the extension can be loaded into Chrome without errors.
Claude gave me three different files, as expected. The most surprising part was the popup UI. Instead of a barebones HTML file, Claude generated a fully styled interface, complete with custom fonts, a color palette, subtle animations, and a small visual identity (including the tomato icon.)
Adding the Pomodoro Timer
With the extension loading correctly, the next step is to make it functional.
At this stage, the goal is not to build the full experience, but to introduce the core mechanic: a working Pomodoro timer. That means adding a countdown, basic controls, and a way to switch between work and break sessions.
Since we already have a popup UI, the task now is to extend it without breaking what’s already there. This time, the prompt needs to be more deliberate. Instead of asking Claude to “create” a timer, we’re asking it to:
- Work with the existing files
- Modify them carefully
- Keep the current UI intact
- Layer functionality on top
Here’s the prompt:
You are working on an existing Chrome extension project called "Pomodoro Tab".
The project already includes:
- manifest.json (Manifest V3, correctly configured)
- popup.html (UI already styled and working)
- popup.js (basic script with a small animation)
Your task is to EXTEND the existing codebase by adding a basic Pomodoro timer.
Do NOT rewrite everything from scratch. Modify and build on top of the existing files.
Requirements:
1. Timer functionality:
- Add a countdown timer (default: 25 minutes for work, 5 minutes for break)
- Display the remaining time clearly in the popup (MM:SS format)
- Include a "Start" button and a "Reset" button
- When the timer ends, automatically switch between work and break sessions
2. UI updates:
- Integrate the timer display into the existing popup.html
- Keep the current design and styling intact as much as possible
- Add buttons in a clean and minimal way (no heavy redesign)
3. JavaScript logic:
- Add timer logic inside popup.js (or split into a new file if clearly needed)
- Use setInterval or similar approach for countdown
- Ensure the timer updates the UI in real time
- Handle start, reset, and session switching cleanly
4. Code quality:
- Keep the code simple and readable
- Do not introduce unnecessary complexity
- No external libraries or frameworks
5. Output format:
- Show the FULL updated code for:
- popup.html
- popup.js
- Only include manifest.json if changes are required (otherwise leave it unchanged)
The result should be a working Pomodoro timer inside the existing extension popup.
Claude produced some nice output. I now have a functional Pomodoro timer that I can start with a 25-minute timer, pause, and reset. There was a problem where, after starting the timer, if I closed the extension or switched tabs, it would stop, and I had to restart it. I explained this to Claude with a follow-up prompt, and it fixed the issue.
Detecting tab switching
With a reliable timer in place, the next step is to observe user behavior. Specifically, we need to know when the user switches tabs. The behavior is simple:
- When the timer is running and hard mode is enabled
- If I try to switch tabs
- The browser immediately forces me back to the original tab
Here’s the prompt I used:
You are working on an existing Chrome extension called "Pomodoro Tab".
Current architecture:
- background.js handles all timer logic and state using chrome.storage and chrome.alarms
- popup.js is a UI layer that communicates with background.js
- Timer persists correctly even when popup is closed
Your task is to EXTEND the project by adding a "Hard Mode" that prevents tab switching during an active session.
Do NOT rewrite existing code. Build on top of it.
Requirements:
1. Hard Mode Toggle (UI):
- Add a checkbox or toggle in popup.html labeled "Hard Mode"
- When enabled, store this setting in chrome.storage
- Default should be OFF
2. Track the active "focus tab":
- When the user starts the timer, store the current active tab ID as the "locked" tab
3. Enforce tab locking:
- In background.js, listen to chrome.tabs.onActivated
- If:
- timer is running AND
- hard mode is enabled AND
- user switches to a different tab
- Then immediately switch them back to the locked tab using chrome.tabs.update
4. Edge cases:
- If the locked tab is closed, disable enforcement gracefully
- Do not crash or spam errors
5. Code structure:
- Keep logic inside background.js
- Keep popup.js focused on UI and messaging
- Use chrome.storage for persistence
6. Permissions:
- Add only necessary permissions (e.g., "tabs")
7. Output:
- Show updated:
- popup.html
- popup.js (if changed)
- background.js
- manifest.json (if changed)
Goal:
When Hard Mode is enabled and the timer is running, the user should not be able to leave the original tab.
Implementing hard mode turned out to be less straightforward than expected. On paper, the idea is simple: detect a tab switch and immediately switch back. In practice, there are a few moving parts: state management, tab context, and timing. That all needs to line up correctly.
The first version Claude generated didn’t work at all. The second worked inconsistently. Only after a couple of iterations did it behave reliably.
A simple yet powerful productivity tool
Most productivity tools are designed to help you stay focused. But when I vibe-coded this product, I assumed that I wouldn’t. Using Claude to build it worked well overall, though there were a few pitfalls along the path. You can find the full code on my GitHub.
