noteloom
← Back to blogWhy we built a React block editor with zero runtime dependencies

13 July 2026

Why we built a React block editor with zero runtime dependencies

Open the package.json of most React rich text editors and you'll find a schema library, a state management layer, or both, sitting underneath the public API. noteloom's dependency list has exactly two entries: react and react-dom.

What that costs you today

A heavier dependency tree means a bigger bundle, more transitive-dependency surface area to patch when a CVE lands, and a schema you have to learn before you can read your own document format. None of that is a knock on those libraries — they solve harder generality problems than noteloom does. But most apps don't need that generality:

  • You are not building a generic document framework for arbitrary schemas — you have a fixed set of block types you actually use.
  • You want to read the stored document without a library-specific decoder.
  • You want one version of react in the tree, not a state library pinned to whatever version the editor bundled.

The actual document model

Every noteloom document is a flat map of two arrays — blocks and runs — not a deeply nested tree. A block references its children by id; a run is a span of text with marks. That's the whole model:

{
  "rootId": "root",
  "blocks": [
    { "id": "root", "type": "page", "contentIds": ["h1", "p1"] },
    { "id": "h1", "type": "heading", "props": { "level": 1 } },
    { "id": "p1", "type": "paragraph" }
  ],
  "runs": [
    { "id": "r1", "type": "text", "value": "Zero dependencies", "marks": {} },
    { "id": "r2", "type": "text", "value": "Just blocks and runs.", "marks": {} }
  ]
}

Flat and normalized like this, it diffs cleanly, stores in a database column as-is, and round-trips straight back into a fresh editor with new EditorStore(json).

📦

The tradeoff is explicit: noteloom covers the blocks and inline types most apps actually reach for, not an open-ended schema for every possible one.


When you'd want something else

If you need a battle-tested, production-proven real-time collaboration stack (Yjs-based operational transforms with years of hardening), or a fully pluggable schema for a document format you don't control, a larger framework still earns its weight — noteloom's own live collaboration (a custom CRDT over WebRTC) is real but explicitly experimental. noteloom is built for the much more common case: a single-user editor, or one that wants peer-to-peer collaboration without standing up a server, embedded in a React app, where every block type is something you defined and own.

The best dependency is the one you didn't have to add.

You can see the full block/run model in action in the Playground, or read the Architecture doc for how the store, registry, and history pieces fit together.

Read the Architecture doc
noteloom.qusere.in/playground

A real, live noteloom instance embedded inside the article. Want the full thing? Open the Playground.