Local-first and progressive web apps

#local-first #pwa

When building apps or imagining software products I like to use and see in the world, I gravitate towards something close to what progressive web-apps embody. An app that is mobile-first, but still usable in any web browser and on any device. An app that works offline, that you can “install” without having to search for it on a bespoke app store or marketplace or proprietary platform. Basically the “write once, use anywhere” concept taken to the maximum. Ever since I came across the principles around local-first software, my interest in progressive web-apps was renewed. It made me wonder: can apps just be like this by default, and also be useful for people who don’t necessarily like to think about software or are interested in it at all, who just want stuff to work? Why is downloading a native app from the App Store a mainstream experience that almost every person understands, but “installing a PWA to your homescreen” doesn’t carry that same level of intuitiveness?

People don’t really care whether their app comes from the Apple App Store, or the Google Play Store or if it’s a progressive web-app (or more generally what technologies something is built with in the first place). But it needs to feel right. I often find, web apps can feel absolutely “right”, and even in popular native apps there is often a large amount of web tech being used in WebViews, without that necessarily being a friction point for the user.

However, I have never installed someone else’s PWA, except the ones I built myself. I guess that says something. And I ask myself, is this really the answer, does anyone really need this? I guess it’s a stretch to say PWAs are popular, but also how would one really know how much they are used in the wild?


I recently set out to become more familiar with the stack around the “local-first” paradigm. Trying to build something that feels like it can really fulfill all those ideals that I have around my understanding of “how apps should be”. It’s a website. It’s built with web technologies. Yet, you can just “install” it on your device. Any device. It works offline. You don’t need internet to use it. Your data stays on your device.

However: You do have the benefit of cloud magic, you can just keep on working on your laptop after editing something on the train on your phone. Users don’t have to carry the mental load of files that live on their devices nor have to worry about keeping them in sync. It feels like this a very pragmatic compromise between two extremes: “I use files and dedicated software to work on these files, I manage backup and sync myself/with some other service” vs. “I do not know what a file is, my digital life lives in random apps from the app store”

You get the benefits of a seamless out-of-the-box UX, while still having control and access to your data. You do not have this central dependency on a third-party server which can completely shut off your workflow and access. It seems like the perfect middle ground.

I have built a very simple app to expose myself to this approach more. A habit tracker. It’s simple enough, I am the kind of person who uses such apps daily (without overdoing it), because I like the structure it gives me. Feeling like this is the perfect use case and being motivated by the thought of replacing a 30€/year SaaS subscription I have to another app I set out.

The core sync stack I ended up with was the following:

TanstackDB

ElectricSQL

Postgres

TanstackDB was the piece I was missing to get started, because it made this whole topic of sync engines approachable. The mental model of a reactive client store that I built my browser app against, and that store by itself taking care of talking to the server really resonated with me.

Hosting ElectricSQL, wiring it up with TanstackDB and Postgres was more straightforward than I expected. This project was also at a real sweet spot for me in terms of using AI to build. I felt quite new and a bit out of the water with all the details of this stack, but had a solid understanding of the overall architecture I wanted to go for. My first eureka moment was opening the app on my laptop and phone side by side and realizing, if I mark the habit done on the laptop as done it is also immediately marked done on my phone.

However, without AI and the hard work put into these libraries, I realized I would have been stuck a lot longer. The complexity of this setup feels so much higher than the typical API request/server response model and there are so many more things that can break.


After this exploration I’m still wondering: Could/Should mainstream apps be like this? Just websites you download and “have” on your device. You log in with a passkey, and you’re authenticated. You lose internet connection and you don’t notice. I like the idea. Yet native platforms have a place, because they can offer experiences the web was just never built for.

Sometimes I feel the idea of (progressive) web apps is just doomed and no one really cares. After all, why would they? What makes a web app better actually, other than some personal ideals of how things should be? Something I am still unsure about. Their principles feel right, yet something seems to not catch people’s interest. Whether that will change, who knows. For now, I will probably keep gravitating towards that.