Three Paradigms

Inline / Document Model

ProseMirror, Tiptap, Slate
Helloworld!
Another paragraphwith mixedformatting

The document is a tree of nodes with inline marks. Text runs freely across the document with marks (bold, italic, etc.) applied as ranges. Maximum flexibility for inline formatting.

Pros: Rich inline formatting, complex nesting, schema validation, collaboration-friendly
Cons: Complex implementation, harder to serialize, steeper learning curve

Block-Based

Editor.js
πŸ“ Paragraph block
πŸ“Œ Heading block
πŸ–Ό Image block
πŸ“‹ List block

Each block is independent with its own type, data, and rendering. Blocks are the atomic units β€” you can't have inline content spanning blocks. Clean JSON output.

Pros: Simple data model, easy custom blocks, clean JSON, drag-and-drop
Cons: Limited inline formatting, no cross-block selections, less sophisticated editing

Hybrid (Block + Inline)

BlockNote, Notion, AFFiNE
ΒΆ Helloworld!
H Title withformatting

Blocks are the container units, but each block contains rich inline content. Combines block-level structure (drag, reorder, nest) with inline-level formatting (bold, italic, links).

Pros: Best of both worlds, Notion-like UX, block operations + rich inline
Cons: Most complex to build, cross-block operations tricky, newer/less proven

Data Model Comparison

Inline Model (ProseMirror/Tiptap)

json
{
  "type": "doc",
  "content": [
    {
      "type": "paragraph",
      "content": [
        { "type": "text", "text": "Hello " },
        { "type": "text", "text": "world", "marks": [{ "type": "bold" }] },
        { "type": "text", "text": "!" }
      ]
    }
  ]
}

Block Model (Editor.js)

json
{
  "blocks": [
    {
      "type": "paragraph",
      "data": { "text": "Hello <b>world</b>!" }
    },
    {
      "type": "heading",
      "data": { "text": "Title", "level": 2 }
    },
    {
      "type": "image",
      "data": { "url": "photo.jpg", "caption": "A photo" }
    }
  ]
}

Hybrid Model (BlockNote)

javascript
// Hybrid approach (BlockNote, Notion)
// Blocks contain inline content with marks
{
  "type": "paragraph",
  "content": [
    { "type": "text", "text": "Hello ", "styles": {} },
    { "type": "text", "text": "world", "styles": { "bold": true } }
  ],
  "props": { "backgroundColor": "yellow" }
}

Feature Comparison

FeatureInline (ProseMirror)Block (Editor.js)Hybrid (BlockNote)
Inline formattingFull (marks system)Limited (HTML in blocks)Full (styled text)
Block drag & dropPlugin neededBuilt-inBuilt-in
Nested blocksVia schemaNoYes
Custom blocksNodeViewsTool pluginsCustom types
Cross-block selectionYesNoLimited
CollaborationOT / CRDTNot built-inYjs (CRDT)
Data formatJSON treeFlat JSON blocksNested JSON
Learning curveSteepEasyModerate
Markdown supportVia serializerNoBuilt-in

Ecosystem

ProseMirror

The gold standard for inline document editing. Powers Atlassian, NYT, Tiptap, Milkdown.

Inline

Editor.js

Simple block editor by CodeX. Clean JSON output, easy custom blocks. Good for CMS.

Block

BlockNote

Modern hybrid editor built on ProseMirror + Tiptap. React-focused, Notion-like UX.

Hybrid

BlockSuite / AFFiNE

Next-gen block editor framework. CRDT-native, supports canvas + doc modes.

Hybrid

Lexical (Meta)

React-focused editor with its own document model. Hybrid approach, extensible nodes.

Hybrid

Slate

React-only editor framework. Custom rendering, plugin-based. Flexible but React-locked.

Inline

Recommendation

When to use what
  • Content writing / docs: Inline (ProseMirror/Tiptap) β€” maximum formatting flexibility
  • CMS / structured content: Block (Editor.js) β€” clean data model, easy custom types
  • Notion-clone / knowledge base: Hybrid (BlockNote) β€” best UX for drag-and-drop + rich text
  • Markdown-first: CodeMirror 6 or Milkdown β€” markdown as source of truth