Building Taddly - A focus timer for macOS

June 25, 2024

Last week I started building a new macOS app, this isn't my first time exploring making Swift apps, but it's certainly the first time I had the time to sit down and build something from start to finish without getting sidetracked. (Thanks to my sabbatical!)

First off, I am by far enjoying my experience writing Swift and building an actual app I can run on my computer, or heck have my Grandma run on her computer. That's right my grandma is cool, she uses a Mac. 😎

It started with a goal

I wanted to build a free focus timer app that worked in the style of Pomodoro Timers, but had just the bare minimum features to explore different aspects of the world of App Dev. Two big features for me were showing the timer in the menu bar and Website Blocking.

Why a focus app, there's hundreds of apps like it?

First off, it's an idea that people know how it works so limited teaching is required to use the app, you download and run it and press Start on the timer. Away you go to focus on your task 😄. Second, it the idea needed to be executable by someone with little Swift / Apple API Knowledge, so I wouldn't feel overwhelmed and give up again.

Choosing to distribute outside of the App Store

For this app for macOS I chose to self-distribute. This left me with a huge issue to overcome which is "How do I notify & deliver updates to users without them needing to re-download and install the app from the website?". Turns out this is actually really a complicated process but it's made easier with an open-source package named Sparkle. I could write a whole blog post on this subject so if you're interested in that let me know.

The Two Big Features

I mentioned earlier about two big features (besides the whole timer counting down thing) was Showing the Timer in the Menu Bar and Website Blocking.

My first project after I got the basic timer working in its own window was to add a Menu Bar Extra, this is something that's actually really a breeze with the SwiftUI API. However after implementing it, I realized it wasn't seemingly possible to update the Menu Bar Extra icon/label in real-time to count down the timer, it just wouldn't update when the timer ticked down. Bummer.

So there I was, crushed that I might not be able to pull off this feature of my app... when I learned about the older APIs NSStatusItem Cool! It seemed doable, but since it wasn't really SwiftUI I didn't know where to start. Luckily I found a blog post by someone on the internet who needed to make a Status Item that had popovers and supported dynamic content in the Menu bar.

That was the first time in a long time I got an endorphin boost once I got things working.

The second feature Website Blocking, was much more difficult to accomplish, and I spent around 10 hours working on it... with 8 of those hours me stuck scouring the web for information on how to pull off blocking websites. I kept being lead to the Screen Time API which sadly doesn't seem to be well supported on macOS, but I'll be making use of it when I port the app to iOS for sure. So then I went down a rabbit hole of using NetworkExtensions and basically trying to be in control of the network request if it should be processed or dropped... but this felt icky so I stopped after a few hours when I couldn't get it working right. Then I went back to using a Safari Content Blocker extension, which I had discarded the idea of that earlier when I originally wanted to make a blocker that worked in all browsers.

Oh well, I gave up that idea and decided to keep it simpler and use the Safari Extension. It works for me since I use Safari as my primary browser, so no sweat there. Once I got the method down, it was a matter of 1) recording the domains people want blocked, 2) adding them to the BlockList.json file and reloading the extension from the app.

With that, I had working website blocking in Safari. Good enough for v1.0.

Next up: Implement little features to delight users

Just today, while working on Taddly... I wondered "How do apps add Shortcuts?" the answer was unsurprisingly App Intents. I spent some time implementing some basic intents for things like Start/Stop/Toggle Timer so hopefully it'll be useful for those who go shortcut crazy, I'm here for it.

I worked on adding a Widget, that hasn't made it into the final app yet because it's not working (good reason to keep it out, amirite), but that's on my list to support.

I spent the rest of my weekend and early part of Monday adding polish, so things like Onboarding screens and polishing up existing views before I'll feel comfortable releasing the link to everyone. I also need to finish the website for the app, which is exciting because I am using Cloudflare Pages to host it and it's a matter of drag-n-drop the folder to upload and deploy. Kinda like it was back in the early 2000s with FTP, a much simpler time for the web.

It brought back the joy of coding...

I've been doing Ruby on Rails development for nearly a decade and the novelty of it has started to wear off for me. But working on Taddly from the start to finish has brought back joy to coding and figuring out how to solve problems I haven't got the slightest clue how to solve.

Why a free app?

I wanted to make my first macOS app free, because it's a crowded market and to be honest there's not a whole lot of reason to pay for Taddly in the first place, it doesn't offer any kind of metrics (yet, it's on my list!) and so there's not a ton features to pay for yet.

Also, I just think it'd be neat to know people find value in my app even if it makes me 0 money.

Why not open-source it?

I'm ashamed of the code, it looks like someone's first production app with Swift, because it's my first production Swift app. Heck, I haven't really committed any commits to it since I made it, I've just been writing it on one computer with no backups 😅.

What other features do you think will come?

For starters, I'm pretty happy with the app how it is, I've been using Taddly while I build it and it's helped me focus.. but as part of using it I have some more ideas on ways to improve it.

No promises these will come but here goes anyway:

  • A iOS and watchOS companion app

  • Widget support

  • Blocking Apps / Websites on iOS (via Screen Time)

  • More customization to come, like the ability to set custom lengths for sessions/breaks. This is now partially implemented

  • Finish adding shortcut support, bring the same shortcuts to Siri and iOS 18 when that's out

  • Metrics for # of sessions completed per day or hours in Focus mode vs Rest mode

  • Customizable Session Title (IE Name it "Work on X") This is now implemented

  • A commitment mode, where you can't pause, skip or restart sessions

  • Skipping sessions (lol, need to implement this still)

  • Accessibility improvements

  • Internationalization support for multiple languages

Bringing the app to the iOS store will be a journey in its own, but I think it's possible. Maybe the iOS app won't be free (if it'd cost anything I suspect under $5), we'll see in the future when I get around to it.

Anyway, this is long enough, let's call it there for now. Building Taddly has brought me a lot of joy so far and

If you're interested you can download Taddly today:

https://taddly.app.