Earlier quoted context omitted.
It looks like I was missing a www subdomain CNAME for the underlying github pages site. I think it's fixed now.
I still see the same error
Linear sent me down a local-first rabbit hole
31–40 of 228 posts
Re: Linear sent me down a local-first rabbit hole
#32Earlier quoted context omitted.
It’s a developer writing about a tool they like. If you’d call word of mouth an “ad” the I guess it’s one.
Well, perhaps it's an AI writing about a tool... > No API routes. No request/response cycles. No DTOs. Just… objects that magically sync. It kind of feels like cheating.
> What makes this powerful is that these aren’t just type definitions - they’re live, reactive objects that sync automatically.
Is what twigged my AI radar too. LLM’s seem to really love that summarisation pattern of `{X is/isn’t just Y. Pithy concluding remark}`
Re: Linear sent me down a local-first rabbit hole
#33ElectricSQL and TanStack DB are great, but I wonder why they focus so much on local first for the web over other platforms, as in, I see mobile being the primary local first use case since you may not always have internet. In contrast, typically if you're using a web browser to any capacity, you'll have internet. Also the former technologies are local first in theory but without conflict resolution they can break dow…
Because building local first with web technologies is like infinity harder than building local first with native app toolkits. Native app is installed and available offline by default . Website needs a bunch of weird shenanigans to use AppManifest or ServiceWorker which is more like a bunch of parts you can maybe use to build available offline. Native apps can just… make files, read and write from files with whatever…
Re: Linear sent me down a local-first rabbit hole
#34I'm also building a local first editor and rolling my own CRDTs. There are enormous challenges to make it work. For example the storage size issue mentioned in the blog, I end up using with yjs' approach which only increase the clock for upsertion, and for deletion remove the content and only remain deleted item ids which can be efficiently compressed since most ids are continuous.
In case you missed it and it's relevant, there was an automerge v3 announcement posted the other day here which claimed some nice compression numbers as well
Re: Linear sent me down a local-first rabbit hole
#35Earlier quoted context omitted.
A web request to a data center even with a very fast backend server will struggle to beat 8ms (120hz display) or even 16ms (60hz display), the budget for next frame painting a navigation. You need to have the data local to the device and ideally already in memory to hit 8ms navigation.
This is not the point, or other numbers matter more, then yours. In 2005 we wrote entire games for browsers without any frontend framework (jQuery wasn't invented yet) and managed to generate responses in under 80 ms in PHP. Most users had their first bytes in 200 ms and it felt instant to them, because browsers are incredibly fast, when treated right. So the Internet was indeed much faster then, as opposed to now. J…
The techniques Linear uses are not so much about backend performance and can be applicable for any client-server setup really. Not a JS/web specific problem.
Re: Linear sent me down a local-first rabbit hole
#36> For the uninitiated, Linear is a project management tool that feels impossibly fast. Click an issue, it opens instantly. Update a status and watch in a second browser, it updates almost as fast as the source. No loading states, no page refreshes - just instant, interactions. How garbage the web has become for a low-latency click action being qualified as "impossibly fast". This is ridiculous.
It is specifically to do with behaviour that is enabled by using shared resources (like IndexedDB across multiple tabs), which is not simple HTML.
To do something similar over the network, you have until the next frame deadline. That’s 8-16ms. RTT. So 4ms out and back, with 0ms budget for processing. Good luck!
Re: Linear sent me down a local-first rabbit hole
#37Earlier quoted context omitted.
This is not the point, or other numbers matter more, then yours. In 2005 we wrote entire games for browsers without any frontend framework (jQuery wasn't invented yet) and managed to generate responses in under 80 ms in PHP. Most users had their first bytes in 200 ms and it felt instant to them, because browsers are incredibly fast, when treated right. So the Internet was indeed much faster then, as opposed to now. J…
Unless you are running some really complicated globally distributed backend your roundtrip will always be higher than 80ms for all users outside your immediate geographical area. And the techniques to "fix" this usually only mitigate the problem in read-scenarios. The techniques Linear uses are not so much about backend performance and can be applicable for any client-server setup really. Not a JS/web specific proble…
But the industry is going the other way. Building frontends that try to hide slow backends and while doing that handling so much state (and visual fluff), that they get fatter and slower every day.
Re: Linear sent me down a local-first rabbit hole
#38Earlier quoted context omitted.
Well, perhaps it's an AI writing about a tool... > No API routes. No request/response cycles. No DTOs. Just… objects that magically sync. It kind of feels like cheating.
That and the paragraph above: > What makes this powerful is that these aren’t just type definitions - they’re live, reactive objects that sync automatically. Is what twigged my AI radar too. LLM’s seem to really love that summarisation pattern of `{X is/isn’t just Y. Pithy concluding remark}`
Watching Tuomas' initial talk about Linear's realtime sync, one of the most appealing aspects of their design was the reactive object graph they developed. They've essentially made it possible for frontend development to be done as if it's just operating on local state, reading/writing objects in an almost Active Record style.
The reason this is appealing is that when prototyping a new system, you typically need to write an API route or rpc operation for every new interaction your UI performs. The flow often looks like: - Think of the API operation you want to call - Implement that handler/controller/whatever based on your architecture/framework - Design the request/response objects and share them between the backend/frontend code - Potentially, write the database migration that will unlock this new feature
Jazz has the same benefits of the sync + observable object graph. Write a schema in the client code, run the Jazz sync server or use Jazz Cloud, then just work with what feel like plane js objects.
Re: Linear sent me down a local-first rabbit hole
#39This architecture offers several advantages:
1. Data is stored locally, resulting in extremely fast software response times 2. Supports convenient full database export and import 3. Server-side logic is lightweight, requiring minimal performance overhead and development complexity, with all business logic implemented on the client 4. Simplified feature development, requiring only local logic operations
There are also some limitations:
1. Only suitable for text data storage; object storage services are recommended for images and large files 2. Synchronization-related code requires extra caution in development, as bugs could have serious consequences 3. Implementing collaborative features with end-to-end encryption is relatively complex
The technical architecture is designed as follows:
1. Built on the Loro CRDT open-source library, allowing me to focus on business logic development
2. Data processing flow: User operations trigger CRDT model updates, which export JSON state to update the UI. Simultaneously, data is written to the local database and synchronized with the server.
3. The local storage layer is abstracted through three unified interfaces (list, save, read), using platform-appropriate storage solutions: IndexedDB for browsers, file system for Electron desktop, and Capacitor Filesystem for iOS and Android.
4. Implemented end-to-end encryption and incremental synchronization. Before syncing, the system calculates differences based on server and client versions, encrypts data using AES before uploading. The server maintains a base version with its content and incremental patches between versions. When accumulated patches reach a certain size, the system uploads an encrypted full database as the new base version, keeping subsequent patches lightweight.
If you're interested in this project, please visit https://github.com/hamsterbase/tasks