# The product mindset

If you are like me, you’ll feel a constant tension between all those new cool side-projects ideas you have and the other things competing for your time/attention (work™, for instance).

I find it pretty useful to filter things off through a product mindset to decide what to do next. This blog post tells how I leverage such mindset. Typically, things (aka “product discovery”) go through a feedback loop:

  1. Identify one or more opportunities (find users’ pain).
  2. Prototype a minimal solution and test it.
  3. Gather feedbacks and iterate.

In most cases, side projects ideas will sparkle from my own pain. I will be the early adopter, but also the builder. “Business”-like pressure comes from the limited time I have to work on side things. This means I need to minimize how much I invest (output, time, lines of code, architectural stack), while maximizing impact. Doing just bare minimum to solve the perceived pain.

# The opportunity: Quickly save things for later

I love reading blog posts and web articles, and I love doing it through RSS feeds.

Sometimes, I’ll find a promising (but long) read on the web. I’d like to store it somewhere so that I can read it later. And I’d like to do it quickly, from my phone. There are a lot of archival/bookmarking tools out there that do that.

For instance, I have self-hosted Wallabag for a while. I could use the iOS Wallabag app to add new entries for later and then consume them through Wallabag’s RSS feed. So far, so good. The problem was that performance was abysmal. I experienced tail latencies of 60 seconds or more when adding new items. Worse, the UI of its iOS mobile app would be blocked for that long, waiting for server-side confirmation.

# A minimal solution: URLs to RSS entries

The bad I/O of the machine hosting Wallabag was most likely what caused my troubles with it. As Wallabag receives a new item, it fetches its content, process it, and make it available for reading. All this happens on a foreground process that, on the hardware where I was running it, was really slow!

Thinking more about this, I realized I didn’t really need to do things synchronously. In fact, most times I’ll save something and read it only after a lot of time has passed. In addition, Miniflux – the feed reader I use – provides support to “Fetch original content” through background workers.

So, a minimal but good solution that works for me only needs to:

  • Map URLs to RSS feed entries.
  • Provide an iOS client.
  • Be quick!

Miniflux will take care of the rest by consuming the feed entries, fetching them, and making them available to clients.

# Zap-It ⚡

Here comes Zap-It ⚡: I saw the opportunity to build something very small that does one thing only, but does it well.

Zap-It reads web entries (a link and a title) from a REST API, stores them in a sqlite database, and serves through an RSS feed. That’s all! Even on a potato-powered machine, it runs fast enough.

This philosophy makes it minimal and doesn’t reinvent the wheel. For instance, Zap-It doesn’t implement access control, but delegates it to existing and battle-tested solutions (the GitHub README provides a few examples).

Full disclosure – I confess that I also wanted to build this to:

  • Experiment with Rust (obligatory 🦀)
  • Start learning Nix (what all cool kids use these days)

# E2E delivery: iOS shortcuts

You might be thinking:

OK, that’s definitely minimal. But what about the iOS client?

Here comes Apple Shortcuts – poor men’s iOS client.

In short, shortcuts let users build small programs through a no-code UI. They provide different integrations, they accessible from the iOS share sheet, and can take what’s currently on-screen as an input.

All this makes shortcuts perfect to build small, context-aware, clients interacting with light APIs. The UX is also pretty good too – sometimes better than native apps.

It’s easier to show than tell:

Using an iOS shortcut to save one of the articles of this blog. The pleasure of seeing it run, and run fast!

You can find the resulting shortcut here.

# Wrapping things up (and looking back)

Building Zap-It took time, of course. It would have been faster for me to code it in Python instead of Rust/Nix. But there’s pleasure in learning new things too and not everything must be optimized.

Looking back, I should have spent a little more time at the design board. For instance, the first iteration didn’t require a title, but would render entries through their raw URL in the feed reader – not nice.

Thinking about outcome instead: so far, Zap-It serves me well. I use it multiple times per day. It’s fast, and its UX doesn’t get in the way. The iOS shortcut works well and it’s reliable.

More importantly, it is a finished side project. It is minimal but has all I need. While building it, I had such a goal in mind. Focus on the end-to-end flow, don’t get bogged down in technical rabbit holes, think about impact.

I think that went pretty well!