Iroh finally hit 1.0
If the P2P connection layer becomes reliable, a whole class of apps that used to be painful becomes much easier to build. This feels especially well-suited for personal software.
More personal software feels worth building now!
Dial Keys, not IPs. After 4 years and more than 65 versions, iroh 1.0 is here to give you the direct connections you deserve.
We can’t wait to see what you will build!
iroh.computer/blog/v1
New in Loro: Mergeable Containers!
Concurrent Map child container creations no longer overwrite.
This surprising overwrite issue existed in Loro, Yjs, and Automerge. Happy to finally ship a solution!
The fix: make the child ID independent of the creation OpId.
We reuse Loro’s Root Container idea: identity from a unique string. For mergeable children, that string encodes the parent LoroMap key, so both peers derive the same ID.
A Lody user sent us the sweetest little story about how she’s been using Lody and Loro to polish her work. It’s so warm and genuinely adorable.
@troubledskies You made my whole day.
The Loro Protocol repo is now open source!
It contains documentation for the wire protocol, along with TypeScript and Rust implementations of WebSocket clients and servers.
The protocol allows reusing a single connection to join multiple CRDT rooms, such as LoroDoc or the Ephemeral Store. It’s also compatible with Yjs and includes experimental support for end-to-end encrypted LoroDoc synchronization.
Loro Mirror is released! It makes building a collaborative experience much easier. You declare a simple schema and keep using setState. Mirror syncs a typed, immutable view of your app state with CRDTs, so you avoid most of the diff/patch glue
ALT import { LoroDoc } from "loro-crdt";
import { schema, SyncDirection, Mirror } from "loro-mirror";
// 1) Declare state shape – a MovableList of todos with stable Container ID `$cid`
type TodoStatus = "todo" | "inProgress" | "done";
const appSchema = schema({
todos: schema.LoroMovableList(
schema.LoroMap({
text: schema.String(),
status: schema.String<TodoStatus>(),
}),
// $cid is the container ID of LoroMap assigned by Loro
(t) => t.$cid,
),
});
// 2) Create a Loro document and a Mirror store
const doc = new LoroDoc();
const store = new Mirror({
doc,
schema: appSchema,
// InitialState will not be written into LoroDoc
initialState: { todos: [] },
});
// 3) Subscribe (optional) – know whether updates came from local or remote
const unsubscribe = store.subscribe((state, { direction, tags }) => {
if (direction === SyncDirection.FROM_LORO) {
console.log("Remote update", { state, tags });
} else {
console.log("Local update", { state, tags
A quick preview of the new lib: you can setState like React; diffs are computed automatically and fed to the CRDTs. Your app can easily support real-time collaboration, offline editing, versioning.
A quick preview of the new lib: you can setState like React; diffs are computed automatically and fed to the CRDTs. Your app can easily support real-time collaboration, offline editing, versioning.
You can now use Loro in React Native📱✨
The demo below showcases the real-time collaboration between an iPhone (left) and an Android (right) through Loro.
The @loro_dev team is also very responsive. We don’t take adding dependencies lightly, but the library’s quality combined with its team gave us the confidence we needed to bet on them
if you are looking for a real-time collaboration library (based on CRDTs), I highly recommend @loro_dev. it's performant, type-safe, and actively maintained
and I've tried them all
if you are looking for a real-time collaboration library (based on CRDTs), I highly recommend @loro_dev. it's performant, type-safe, and actively maintained
and I've tried them all
New in loro-crdt v1.5.0: Enhanced document control with pre-commit hook, plus EphemeralStore for optimized state synchronization. Now you can build verifiable editing history as Merkle DAGs inside Loro.
In version 1.5, for environments that support multi-threading, such as Rust and Swift, LoroDoc can now be directly and safely shared and accessed in parallel across multiple threads without triggering the previous WouldBlock panic.