Skip to content

Introduction

Plim is a Notion-inspired block editor for the web, built as a TypeScript monorepo. Plim ships a framework-agnostic core, a DOM view layer, a Markdown parser/serializer, and React bindings - all small, composable, and designed to be embedded in your own product.

Plim is split into eleven focused packages. Take only the layers you need.

PackageDescription
@plim/coreSchema, document model, transactions, validation rules, action/extension/trigger system, history, and the built-in block & mark descriptors. Runtime-agnostic - no DOM.
@plim/ledgerRecord, replay, merge, diff, and rebase transactions (TransactionLedger, LedgerRecord) plus conflict resolution - the bring-your-own sync / CRDT layer. Runtime-agnostic.
@plim/transportsTiny generic duplex-channel primitives (Transport<T>): in-memory loopback + broadcast bus, BroadcastChannelTransport, reconnecting WebSocketTransport, and mapTransport codecs. The wire that collaboration and comments sync over. Zero-dep.
@plim/collaborationReal-time multi-peer editing on top of the ledger: Collaborator (optimistic OT), CollabHub (transport-agnostic server half), presence/awareness, and version vectors - plus comments & threaded replies (commentMark, observable CommentStore, CommentSync).
@plim/markdownParse Markdown into a Plim document (contentFromMarkdown, parseMarkdown) and serialize back (contentToMarkdown).
@plim/editorThe view layer. Mounts a Plim document into a contenteditable, owns the floating toolbar, the block-handle gutter, paste/clipboard handling, drag-and-drop, and the keyboard pipeline. Ships its own stylesheet.
@plim/reactReact bindings: <PlimEditor>, useEditorHandle(), slash-command and mention extensions with first-class React components, and a bridge for defining blocks with toComponent.
@plim/mojisSlackmoji-style custom inline emoji (“mojis”). Live-converts :slug: shortcodes as you type or paste, resolves through your own map or an async (cached) resolver for hundreds of workspace emoji, behaves like ordinary text for cursor/selection, and copies back out as :slug: markdown. Ships its own stylesheet. Optional.
@plim/htmlHeadless, SSR-safe serializer: render a document model to an HTML string (serializeToHTML) with overridable per-block / per-mark renderers and escaped-by-default output. No DOM - runs in Node, edge, email, and SEO pipelines. Optional.
@plim/storageDurable persistence primitives: pluggable StorageAdapters (memory, localStorage, IndexedDB, transport) plus debounced snapshot autosave (createAutosave). Optional.
@plim/test-utilsRunner-agnostic testing helpers: fluent document/mark builders, a headless createTestEditor (real driver, no DOM), applyTx, and inspectors/assertions for unit-testing your own blocks, marks, and extensions.
  • @plim/core owns the document model and the transaction system. Everything else builds on it.
  • @plim/editor (and @plim/react on top of it) renders that model and turns user input into transactions.
  • @plim/markdown and @plim/html convert documents to and from other formats.
  • @plim/mojis is an optional editor extension that adds custom inline emoji on top of @plim/editor.
  • @plim/ledger, @plim/transports, @plim/collaboration, and @plim/storage form the sync and persistence layers.
  • @plim/test-utils lets you exercise your blocks and extensions headlessly.