What’s new in Y-Sweet 0.7.0: offline support and more!
2024-12-18
Paul Butler
We recently released Y-Sweet 0.7.0. Here’s a look at what’s new:
Ground-up YSweetProvider
rewrite
At its core, Yjs is an in-memory CRDT data structure. The data structure itself is not aware of the network or storage. Applications can synchronize a Yjs document over a specific transport (like WebSocket or WebRTC) using a provider for that transport.
Until 0.7.0, Y-Sweet used a forked version of the y-websocket provider maintained by the Yjs community. While this is a good provider, it was not amenable to some of the functionality we wanted to build on top of it. For Y-Sweet 0.7.0, we rewrote the provider from scratch, bringing with it better offline support, reconnection logic, and connection/sync status observability.
Offline support
YSweetProvider
now includes IndexedDB support, making offline support as easy as passing offlineSupport: true
when constructing the provider (<YSweetProvider offlineSupport={true} />
if you use our React bindings).
All major browsers store IndexedDB as plain text on disk. To avoid exposing your users’ data, we encrypt the data on the client before we store it in the database, which allows us to piggyback on app-bound encryption in Chrome and Edge. You can read more about this approach in this Browsertech post.
Improved reconnect handling
As part of the rewrite, we made some improvements to the reconnect loop to make it faster and more robust. For example, if the client is in a reconnect loop and the browser fires an online
event, we skip the normal cooling-off period and immediately try to reconnect.
Connection & sync status listeners
Browsers are often slow to detect WebSocket connection closure when the connection is lost — we have observed up to 90 seconds for Chrome on a VPN! As part of the reconnect handling improvements, we extended the protocol with a passive/active heartbeat. When the connection is actively in use, existing inbound traffic plays the role of the heartbeat. During lulls in the traffic, an active heartbeat kicks in.
This status is exposed through a new connection-status
event type, and as useConnectionStatus()
if you use our React hooks.
We also now provide a local-changes
event, which passes a value of true
when a local change is made and false
when all local changes have been received by the server. This is exposed in the React hooks as useHasLocalChanges()
.
Deprecating Wasm/Cloudflare support
Y-Sweet has historically supported two deployment targets: a native Linux app, and a WebAssembly module that runs as a Cloudflare Durable Object. This is possible because most of the underlying implementation belongs in y-sweet-core
, which is designed to support native and WebAssembly targets.
As of 0.7.0, we are deprecating WebAssembly support in y-sweet-core
. Future releases with the 0.7.x minor version will continue to support WebAssembly and Cloudflare deployment. Starting with 0.8.0, WebAssembly will no longer be a supported target for y-sweet-core
, and we will not support Cloudflare deployment.
This was a tough decision. We never like to take away functionality from an open source project. But it has become clear that the need to support WebAssembly as well as native was creating a big burden to contributions both from our own team and the open source community.
Additionally, it became clear that our roadmap was much more tractable if we drop the WebAssembly support. In particular, we have redesigned the storage engine to take advantage of multithreaded execution, which is not available on Cloudflare’s Workers platform.
A core principle of Y-Sweet development continues to be that you should be able to self-host it. To that end, we are building support for Plane directly into Y-Sweet to allow you to run Y-Sweet at scale as a distributed system. (Single-node deployments, which do not require Plane, will continue to work as they do today.)
Managed storage & free tier
We recently announced managed storage for Y-Sweet on Jamsocket. This means that you can create a Y-Sweet project with persistence without attaching your own S3 bucket. You can still attach an S3 bucket if you want to, of course, but that’s no longer a prerequisite.
Along with managed storage, we’ve also introduced a free tier providing 10GB of storage per account.
New resources for getting started
create-y-sweet-app
makes it easier to bootstrap a Next.js or Remix app preconfigured with Y-Sweet.y-sweet-supabase-demo
is an example app showing how Y-Sweet can be used along with Supabase to implement auth, sharing links, and document listings.- Our new BlockNote tutorial shows how to use the Notion-like BlockNote component in a Y-Sweet application.
Welcoming Jake to the team
Jake Lazaroff recently joined the Jamsocket engineering team. You may have seen Jake’s writing on CRDTs around the web (A Local-First Case Study, Making CRDTs 98% More Efficient, Building a Collaborative Pixel Art Editor with CRDTs, An Interactive Intro to CRDTs). Jake's depth of understanding of CRDTs and attention to craft make him a great addition to the team, and I’m excited about how we’ll be able to make Y-Sweet better with Jake on board.
On the horizon
As we round out 2024, we have an ambitious roadmap for Y-Sweet in 2025. Work is already underway on a new storage engine with history support, read-only access tokens, and more.
If you’d like to suggest features, come say hi on Discord or open an issue on GitHub.