Localfirstconf this week, second edition ✈️
What did change in "just" 1 year? Well, a lot.
On my way to Berlin for @localfirstconf ✈️ Expecting a lot from the conferences for local-first ⚡️ @livestoredev 👀 Zero sync 🪄 @tan_stack DB Stay tuned for more updates 🔛
Let me give the simplest overview of local-first after (more than) 1 year of personal explorations 👇
Local-first, but how?
If you are new to the concept of "local-first", here is my one-liner:
Database on the client 🪄
Simple idea, huge implications.
Let's move one step at the time 🚶♂️➡️
Client database
Nothing fancy. You simply store data on the user device, in whatever way possible.
You can consider "client database" as a Glorified Cache™️:
Instead of reading data from the cloud, the UI reads from a local database 💁🏼♂️
That's the first (huge) chuck required to enable local-first (and sync engines in general). What form of storage you choose will dictate most of your final API:
- Local/Session storage (👎)
- IndexedDB
- SQLite (with OPFS)
- PgLite
A lot of research in progress to "solve" client storage, no solution stands out (yet) 🤔
OPFS is still early, limited support in browsers, and overall painful. Therefore, my experiments with SQLite are limited and mostly unsuccessful.
Pglite is growing (features, popularity, ecosystem). I would suggest giving it a try.
IndexedDB has always been a pain. But, since it's the only "real" long-term storage in the browser, I went on a quest to make it better with effect.
I worked on a new
IndexedDbmodule for@effect/platform-browser(PR).More articles and tutorials coming for this 🔜
Sync
So, the UI reads from a client database. It has no awareness of any "cloud".
Problem: the data is "trapped" on the user device 😬
Local-first is also about collaboration. Therefore, we need a way to "update" the client about the latest news from other users.
In practice, something must be running on the background to upload/download updates.
That's the role of a sync engine ⚡️
A lot of research here as well. Two main techniques I explored:
- CRDT (Conflict-Free Replicated Data Type)
- Event sourcing
It's a distributed system problem, aka it's hard 🤯
Many technologies to watch:
Local-first all the way in
Figure out client storage + syncing and you already get most of the benefits:
- Offline support
- Fast UI
- Great developer experience
- Collaboration
But local-first goes a few steps further, aiming for a full user-centric experience.
Privacy
"Complete" privacy is only achievable when all the data lives on the user device.
Collaboration open a whole new set of challenges. Data ownership, authentication, encryption, with all sort of edge cases arise in a distributed model.
Longevity + User control
The user owns his data, completely. A local-first app should allow to export locally all the data (in usable formats), and remove it completely from the intermediate syncing cloud.
Server independence
A user is not locked over a single "sync server". I should be able to keep the same client/UI, and only point to a different sync provider.
Local-first aims to achieved the best UX for the user, full control and no lock-in 🚀
We are getting there
I am in Berlin this week for localfirstconf.
I am writing this before the conference, so you must wait next week for my full report 🫡
But, I can already tell you that the local-first movement is growing. With 3 days of conference, 2 days packed of talks, and many new solutions available.
A staggering progress in just one year (since the previous localfirstconf). Clear signs that you should consider betting on local-first (just like I am doing 🫡)
Meanwhile, my Effect Days 2025 talk is out on Youtube:
This is your 10 minutes get started with frontend effect.
See you next 👋
