<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ursa</title>
    <description>The latest articles on DEV Community by Ursa (@ursa321).</description>
    <link>https://dev.to/ursa321</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3890828%2Fb803cb11-1b13-4515-b14f-5b495311ca88.png</url>
      <title>DEV Community: Ursa</title>
      <link>https://dev.to/ursa321</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ursa321"/>
    <language>en</language>
    <item>
      <title>I got tired of Pomodoro lying to me, so I built a dual-budget desktop timer</title>
      <dc:creator>Ursa</dc:creator>
      <pubDate>Tue, 21 Apr 2026 13:39:42 +0000</pubDate>
      <link>https://dev.to/ursa321/i-got-tired-of-pomodoro-lying-to-me-so-i-built-a-dual-budget-desktop-timer-5aol</link>
      <guid>https://dev.to/ursa321/i-got-tired-of-pomodoro-lying-to-me-so-i-built-a-dual-budget-desktop-timer-5aol</guid>
      <description>&lt;p&gt;Classic Pomodoro has a hidden assumption: once the work timer starts, you should stay focused until it ends.&lt;/p&gt;

&lt;p&gt;That sounds great in theory. In practice, it kept failing for me.&lt;/p&gt;

&lt;p&gt;Sometimes I would get distracted in the middle of a focus session. Sometimes other people would interrupt me. The timer kept running anyway, and when those 25 minutes were over, I had no honest idea how much I had actually worked and how much of that time had been noise.&lt;/p&gt;

&lt;p&gt;At that point, the timer stopped being helpful. It became performative.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;Ketchup&lt;/strong&gt; — a compact desktop timer that keeps the Pomodoro spirit, but changes one rule that made all the difference for me.&lt;/p&gt;

&lt;p&gt;Instead of forcing “work first, break later” as one rigid timeline, Ketchup treats &lt;strong&gt;work&lt;/strong&gt; and &lt;strong&gt;break&lt;/strong&gt; as &lt;strong&gt;two independent budgets inside the same cycle&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If your cycle is &lt;strong&gt;25 + 5&lt;/strong&gt;, then you still owe the cycle &lt;strong&gt;25 minutes of work&lt;/strong&gt; and &lt;strong&gt;5 minutes of rest&lt;/strong&gt; — but you can switch between them whenever real life demands it.&lt;/p&gt;

&lt;p&gt;Got interrupted 8 minutes into work? Switch to break.&lt;br&gt;
Ready again after 2 minutes? Switch back to work.&lt;br&gt;
Need another short pause later? Go for it.&lt;/p&gt;

&lt;p&gt;The cycle only ends when &lt;strong&gt;both budgets reach zero&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That means the timer no longer pretends you worked for 25 uninterrupted minutes when you didn’t. It reflects what actually happened.&lt;/p&gt;

&lt;p&gt;In a way, it feels closer to &lt;strong&gt;a chess clock&lt;/strong&gt; than to a classic Pomodoro timer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this model works better for me
&lt;/h2&gt;

&lt;p&gt;The main problem I had with traditional Pomodoro wasn’t discipline. It was that the model assumed a level of uninterrupted focus that my real workdays rarely have.&lt;/p&gt;

&lt;p&gt;A good productivity tool should survive interruptions, not break because of them.&lt;/p&gt;

&lt;p&gt;This dual-budget approach helped me in a few ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I no longer “lose” work time to random interruptions.&lt;/li&gt;
&lt;li&gt;Breaks are still deliberate, not accidental.&lt;/li&gt;
&lt;li&gt;A cycle stays honest: work is work, rest is rest.&lt;/li&gt;
&lt;li&gt;I can adapt in the moment without throwing away the structure entirely.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It feels less like failing a timer and more like using one.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;Ketchup is a small cross-platform desktop app built with &lt;strong&gt;Tauri v2 + React&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A few things I wanted from it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Free phase switching&lt;/strong&gt; — move between Work and Break at any moment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dual progress rings&lt;/strong&gt; — both budgets stay visible, so the whole cycle is always readable at a glance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Preset and custom configurations&lt;/strong&gt; — easy to change timing setups&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sound transitions&lt;/strong&gt; using the Web Audio API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A compact desktop UI&lt;/strong&gt; with a frameless window and smooth animations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local-first behavior&lt;/strong&gt; — no accounts, no cloud, no ceremony&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also intentionally kept the architecture simple: the timer state machine and UI logic live in the React frontend, while Rust is mostly there to host the Tauri side of the app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Tauri
&lt;/h2&gt;

&lt;p&gt;This project felt like a perfect fit for Tauri.&lt;/p&gt;

&lt;p&gt;I wanted a desktop app that was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;lightweight&lt;/li&gt;
&lt;li&gt;cross-platform&lt;/li&gt;
&lt;li&gt;easy to ship&lt;/li&gt;
&lt;li&gt;pleasant to build UI for&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;React gave me a fast way to iterate on the interaction model, and Tauri made it possible to package that into a native-feeling desktop app without dragging in the overhead of a heavier runtime.&lt;/p&gt;

&lt;p&gt;For a tiny utility app, that combination feels really good.&lt;/p&gt;

&lt;h2&gt;
  
  
  The more interesting part wasn’t the code
&lt;/h2&gt;

&lt;p&gt;Honestly, the most valuable part of building this project was not the implementation.&lt;/p&gt;

&lt;p&gt;It was realizing that many productivity tools fail not because they are badly designed, but because they encode the wrong assumptions about attention.&lt;/p&gt;

&lt;p&gt;The classic Pomodoro method assumes a clean separation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;focus&lt;/li&gt;
&lt;li&gt;break&lt;/li&gt;
&lt;li&gt;repeat&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But real work is messy. Attention is messy. Interruptions are normal.&lt;/p&gt;

&lt;p&gt;So instead of trying to force myself to behave like a perfect timer user, I changed the timer to better match reality.&lt;/p&gt;

&lt;p&gt;That turned out to be much more useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next
&lt;/h2&gt;

&lt;p&gt;I’ve already published the first release, and I’m still polishing the project.&lt;/p&gt;

&lt;p&gt;Things I’m especially interested in now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;feedback on the interaction model&lt;/li&gt;
&lt;li&gt;UI/UX improvements&lt;/li&gt;
&lt;li&gt;ideas for small but meaningful features&lt;/li&gt;
&lt;li&gt;edge cases in timer behavior across platforms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’ve ever felt that Pomodoro is helpful in theory but too rigid in practice, I’d love to hear how you handle that.&lt;/p&gt;

&lt;p&gt;GitHub repo: &lt;a href="https://github.com/Rench321/ketchup-timer" rel="noopener noreferrer"&gt;https://github.com/Rench321/ketchup-timer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Downloads: available in the Releases section&lt;/p&gt;

</description>
      <category>tauri</category>
      <category>react</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
