Colla provides Rust-native Operational Transformation primitives for immutable,
nested values, plus a JavaScript Document model. The same data model, canonical
binary format, and OT semantics are exposed through the synchronous colla-ot
package.
Colla includes:
- immutable
Valuetrees and recursive, canonicalChangevalues; - Apply, Compose, Invert, and pairwise Transform with TP1 guarantees;
- collaborative Text and RichText with atomic embeds;
- typed Rust and JavaScript Change construction;
- a strict canonical binary body codec with configurable input limits.
The JavaScript package exports Document, Snapshot, Update, immutable
Values and Changes, codecs, and OT operations from one package entry point.
Document manages in-memory content and update state, but Colla is not a
complete collaborative document runtime. Applications still own sessions,
history, transport, presence, cursors, and editor-specific formats.
- Document state provides mutable document state, Snapshot persistence, local and remote Update handling, and change events.
- Immutable content and changes provide Values and Changes, canonical codecs, and Apply, Compose, Invert, and Transform operations.
All JavaScript capabilities are exported from colla-ot.
Use Document when the application needs to own current content, apply local
edits, receive ordered remote Updates, create persistent Snapshots, or update
an editor from change events.
import { Document, text } from "colla-ot"
const document = Document.fromJS(text("Draft"))
const unsubscribe = document.subscribe(event => {
console.log(event.origin, event.revision, event.editSteps)
})
// Atomic transaction. Returns a pure Update with no Wasm handles.
// Send update.bytes through your application transport (WebSocket, HTTP, etc.).
const update = document.transact(tx => {
tx.text([], stream => stream.retain(5).insert(" v2"))
})
const updateBytes = update.bytes
// Persist the current visible content and revision when a checkpoint is needed.
const snapshot = document.snapshot()
const snapshotBytes = snapshot.bytes
unsubscribe()Use immutable Values and Changes directly when the caller owns document state or needs pure OT operations.
import { Change, ValueHandle, apply, text } from "colla-ot"
const before = ValueHandle.fromJS(text("Draft"))
const change = Change.build(change => {
change.text(text => text.retain(5).insert(" v2"))
})
const after = apply(before, change)
console.log(after.toJS()) // { type: "text", value: "Draft v2" }colla-ot supports Node.js 22+, Vite 5+, and Rollup 4+. See the
JavaScript guide for Snapshot restoration, remote
Updates, acknowledgements, editor integration, codecs, and the complete JavaScript
API.
use colla::{apply, Change, TextChange, TextOp, Value};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let before = Value::text("Draft");
let change: Change = TextChange::from_ops([
TextOp::Retain(5),
TextOp::Insert(" v2".into()),
])?
.into();
let after = apply(&before, &change)?;
assert_eq!(after, Value::text("Draft v2"));
Ok(())
}The published colla crate supports Rust 1.81 or newer.
The documentation index also links the normative specifications, architecture decisions, roadmap, release runbook, domain language, and changelog.
Run pnpm docs:dev for a local preview of the official documentation site.
Run Rust tests with cargo test --workspace --all-targets and JavaScript
artifact tests with pnpm test:js.