6
11 Comments

How I built a native Mac app to solve my own break-time doomscrolling habit

Hey IH! 👋

I wanted to share a project I've been working on, along with the technical, architectural, and design choices behind its latest release.

The Problem I Was Facing
During long focus blocks at my desk, every time a Pomodoro break arrived, I’d default to picking up my phone and scrolling social media for 5 minutes. I'd return to my work feeling more distracted than before, while my growing queue of EPUBs and technical PDFs sat completely untouched.

The Solution: Bookidoro
I built Bookidoro — a native macOS app that lives in the menu bar. Instead of telling you to step away and leaving you to scroll your phone, when a work interval ends, it opens a calm overlay displaying the next 1–5 pages of your book right on your screen.

You read a couple of pages, click Done, and get right back to work. Doing 2 pages per break × 6 breaks a day adds up to ~12 pages daily—about one full 250-page book every month without needing to "find extra time."

⚙️ Key Technical & Architectural Choices

  1. Multi-Mac Native iCloud Sync (Zero Third-Party Servers)

In the latest updates (v0.5.0–v0.6.0), I added full library, reading position, and stats sync across devices using native iCloud Drive.

Drop-In Books: Users can drop a PDF or EPUB directly into iCloud Drive → Bookidoro, and it automatically appears in the library across all their Macs.

Privacy-First: By leveraging Apple's native iCloud APIs, I don't need to run or maintain custom backend servers, handle user auth, or store user books on external databases.

  1. Native macOS Polish & Meeting Awareness

Built purely for macOS 13+ (Apple Silicon & Intel). No Electron overhead, no Dock icon clutter, and zero focus stealing while typing.

Smart Meeting Detection: To avoid interrupting deep work or presentations, the app reads macOS system flags for active mic, camera, or screen-sharing usage (Zoom, Meet, Slack, Teams) and defers the break until ~1 minute after the call ends.

  1. Reading Flow Controls & Rendering

EPUBs reflow into clean typography, and PDFs retain exact layout fidelity. Added custom paper themes and a true Night Mode that recolors PDF backgrounds to dark gray without ruining image contrast.

Granular reading controls like "Look Back" (← Previous page), "Keep Reading" (fetch 5 more pages in the same break), and "End Here" (pause mid-break on a specific sentence).

  1. Monetization Model

Free to use forever with all core features unlocked.

Added a low-friction $9.99/year license key via Gumroad that removes a small daily reminder card for users who want to support independent macOS development.

Check out the app at https://bookidoro.app. Looking forward to hearing your thoughts!

on September 28, 2026
  1. 1

    The "click Done and get back to work" beat is my favorite part — a small, clear finish line is what makes a break feel complete instead of an open loop. Also like the free-forever core + light $9.99/yr supporter key; keeping the core honest and charging to remove the nudge feels a lot fairer than gating the reading itself. Curious how often people hit "Keep Reading" — that'd be a great signal the pages are actually landing.

  2. 1

    Nice idea, replacing the habit instead of just blocking it. One suggestion on first-run: the whole value shows up at the first break, but that only happens if the user has already imported a book. A lot of people will install, not have an EPUB handy, and the first break arrives with nothing to show. Bundling one or two short public-domain books (or a "pick a free classic" screen during onboarding) means the first break always works, and then you can treat "completed first reading break" as your activation metric instead of installs. On distribution, r/macapps, Mac-focused newsletters and Pomodoro or reading communities feel like a natural fit since the use case explains itself in one GIF of the overlay popping up.

  3. 1

    The one number in here that is load-bearing is the twelve pages a day, and it is the only number in the post that is derived rather than measured.

    Two pages per break times six breaks is an arithmetic fact about your own defaults, not an observation about anyone's day. The two pages come from you, which is fine. The six breaks are the assumption doing all the work, and it collides with the feature you built specifically because that assumption breaks: meeting detection exists because breaks and calls do overlap, and every deferred break pushes the daily total down. Each deferral also re-times the next interval, so the six is not a floor that survives a busy Tuesday, it is a best case that a normal calendar erodes from the top. The same caution applies to the month, because two hundred and fifty pages is only reachable if the average session clears two pages across a full month of days that include travel, sick days and weeks where the habit slides.

    What makes this worth separating is that every other claim in the post sits on a different footing. iCloud sync, the menu-bar architecture, the system flags for mic and camera, the PDF rendering - those are properties of code, they hold or they do not, and you can verify them yourself. The pages-per-day figure is the only one pointed at the user's life, and it is the only one that has never been observed in the wild. If real sessions land at three or four breaks rather than six, the honest pitch is closer to half a book a month, which is still a real gain but no longer the same argument, because the comparison then stops being the app against scrolling and becomes the app against simply opening the book later. That is a harder comparison and it needs a real denominator rather than a tidy one.

    Disclosure, since it bears on the above: I build Piramyd, so adoption claims that survive measurement rather than assertion happen to align with what I sell.

    Of the two assumptions, which one do you expect to survive contact with real users - the two pages, or the six breaks?

  4. 1

    Great inside!

  5. 1

    I’d compare return to task time after light versus technical reading which is a bit more than just completed. Are you tracking anything like that?

  6. 1

    scratching your own itch is the best product spec - you are the user, so the feedback loop is instant. we built swapfile.live the same way (needed file conversion without uploads, nothing good existed). did solving your own problem make marketing easier or harder, since you're so close to it?

  7. 1

    Bookidoro’s best insight is making the break replacement easier than reaching for the phone—two pages at a time turns willpower into a tiny default. Meeting detection plus native sync is a lot of edge-case territory, but at least the app is fighting doomscrolling with PDFs instead of another notification 😄

  8. 1

    Local-first with no account is the right shape for a menu-bar reader. The failure I'd test before leaning on iCloud is two Macs both mid-break: last-write-wins on reading position will jump you backward and people will blame the timer, not sync. Meeting detection via mic/camera is what makes this usable, but I'd add a manual "I'm presenting" override — some call apps never set those system flags. The $9.99/year to hide a reminder is fine only if the free path never nags mid-page.

    1. 1

      Last-write-wins on reading position is worse than a lost update, and it is worth being precise about why, because the fix people reach for first does not help.

      The intuitive repair is a timestamp, or a version counter, or last-modified-wins with a tiebreak. None of those fix this case, because timestamps order events by wall clock and the problem here is causal, not chronological. Two Macs both mid-break means the two writes are genuinely concurrent: neither happened before the other, so there is no correct winner to pick and any rule you choose is inventing an order that the user's actual behaviour never produced. Where the two devices are on the same account, clocks can also disagree, so the device with the earlier logical write can win on time and still be the wrong page. That is why the failure lands on the timer: from the user's seat the overlay jumped backward with no action of theirs, and the timer is what they can see.

      The distinguishing question is whether a merge is meaningful at all. A reading position is the kind of value you can combine rather than choose: the honest merge is the furthest point both devices have already covered, because position is monotonic within a book. Reaching two pages further on the laptop should not be undone by the phone finishing earlier on a page you already read. That is a mergeable value with a simple rule, and it does not need a clock. What genuinely is last-write-wins is the small side data: the theme you last picked, the stats counter increment, whether the reminder card was dismissed. Those are not monotonic and picking a winner is fine. One CRDT for position, plain last-write-wins for the rest, rather than one policy stretched across both.

      Your manual override point holds and I would generalise it: system flags are a signal that some app decided to expose, so the list of apps that set them is a subset of the apps that use the mic. A menu-bar item that lets you say "not now" for the next hour covers every app you forgot to test for, which is cheaper than detection that stays correct.

      Since my last comment above was on the same post, the same disclosure applies: Piramyd is what I build, and merge semantics on sync are close enough to that to be worth saying out loud.

      When two devices disagree on position, would you rather the app take the maximum and admit the merge, or refuse and ask the user which one is right?

  9. 1

    Have early users actually kept Bookidoro in their break routine, or is the strongest signal so far that the workflow makes sense conceptually?

    1. 1

      I dont have massive user base to make analysis, but based on users I have right now and by me retention is good.