A self-hosted, real-time collaborative markdown notebook. Several people on one page at once with nothing to resolve by hand, IDE-grade diagnostics on prose, per-actor undo that survives interleaved edits, and history you can scrub — because the operation log is the truth.
Status: running in production. Six Rust services behind a gateway, four Postgres instances, NATS and Redis — thirteen containers, live at marginal.genuinebasil.dev. The repository also holds the architecture, the data model, eleven ADRs, and the roadmap for the Rust port now under way.
The roadmap marks each phase by Rust density. These are the ●●● ones — where the work is genuinely hard and no crate is doing it for me.
| FROM → TO | TRANSPORT | SHAPE | WHY THIS AND NOT THE OTHER |
|---|---|---|---|
| browser ↔ collaboration | WebSocket | bidi | edits and cursors flow both ways continuously; nothing else fits |
| gateway → collaboration | WS + hash route | sticky | every client on a page must reach the same stateful instance |
| collaboration → document | NATS JetStream | async event | the projection may lag; the editor may never wait on it |
| collaboration → diagnostics | NATS JetStream | fire & forget | degradable by design — no squiggles beats no typing |
| document → search | gRPC | client stream | bulk reindex is a stream of many small writes, not one big call |
| history → document | gRPC | unary | cold path — latency here costs nothing anybody feels |
| gateway → auth | local verify | no call | the RS256 public key is cached; auth is never on the hot path |
Ticked phases are running in production today. Order is a dependency question, so it lives in the roadmap; when is an estimate and does not. Track 1 deliberately ends on the deepest phase — shipping the MVP early costs no depth. Cloud is not a track at the end: a phase is not done until its increment is deployed.