All comparisons

Engine ↔ Engine

SpineEditor vs ProseMirror

ProseMirror is the most influential open-source editor engine on the web. It powers Atlassian, Asana, The New York Times, Reedsy, and the early versions of Notion. SpineEditor sits at the same architectural layer — a foundational engine — and is best compared to ProseMirror directly, engine-to-engine.

What ProseMirror does well

  • Schema-driven core. Define node types, mark types, and content expressions; the engine enforces them. Custom node types are first-class.
  • Decorations. Attach UI to ranges of the document without changing the document itself.
  • Tables and collaboration packages. prosemirror-tables and prosemirror-collab are battle-tested official extensions.
  • Mature ecosystem. A decade of issues, talks, blog posts, and packages built around it.

What SpineEditor does at the engine layer

  • Explicit Plan stage. ProseMirror commands return a transaction directly; the planning is implicit. SpineEditor compiles every Intent into a Plan artifact you can read, log, or reject before any state mutates.
  • Determinism contract. The pipeline is fixed: Intent → Plan → Transaction → Apply → Normalize → Commit. Every stage produces named artifacts you can inspect.
  • Built-in trace and replay. Every commit emits structured trace data; reconstruct any session deterministically without custom tooling.
  • TypeScript-first. The source is TS; types are part of the public contract, not bindings layered on after.

Engine architecture

Architectural layer

ProseMirror
Engine
SpineEditor
Engine

Pipeline contract

ProseMirror
Transaction-driven
SpineEditor
Intent → Plan → Transaction

Explicit plan artifact

ProseMirror
SpineEditor
First-class

Built-in trace / replay

ProseMirror
Custom tooling
SpineEditor
Built-in

Document model

ProseMirror
Schema-driven
SpineEditor
Canonical schema

Source language

ProseMirror
JavaScript + types
SpineEditor
TypeScript

License

ProseMirror
MIT
SpineEditor
MIT

Code: insert text at the caret

ProseMirror:

import { EditorState, Transaction } from "prosemirror-state";

const tr: Transaction = view.state.tr.insertText("Hello");
view.dispatch(tr);

SpineEditor:

engine.dispatch({
  kind: "typeText",
  text: "Hello",
});

Choose ProseMirror if

  • You want the largest ecosystem of community plugins and battle-tested patterns.
  • You're comfortable writing schema, commands, and plugins by hand.
  • You want full control over every layer of the editor.

Choose SpineEditor if

  • You want every edit to produce an inspectable Plan artifact before mutation.
  • You need replayable, deterministic editing for testing or audit.
  • You want an engine where the pipeline is the contract, end-to-end.
  • You want TypeScript types throughout the public surface.