dorfteich/docs/architecture/adr/0004-tiptap-editor.md
Claude Fable 5 0629411966 Add architecture documentation, ADRs, and operations concept
Initial deliverable of the architecture phase: 16 ADRs (stack, CRDT
collaboration, plugin sandbox, import/export, backups, CI/CD), data
model, permission model, real-time collaboration and plugin concepts,
deployment/operations/security documentation, and the milestone roadmap
that the implementation issues are derived from.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 14:36:16 +02:00

2.7 KiB

ADR 0004: TipTap (ProseMirror) as the WYSIWYG editor

  • Status: accepted
  • Date: 2026-07-04

Context

Dorfteich needs a WYSIWYG editor with: collaborative cursors, CRDT binding (ADR 0003), Markdown-friendly copy/paste, image paste from the clipboard, link editing UX (edit URL / open in new tab), and a schema that plugins can extend with custom block types (ADR 0008).

Decision

  • TipTap (MIT-licensed core, built on ProseMirror) is the editor framework, used with:
    • @tiptap/extension-collaboration — binds the document to Yjs,
    • @tiptap/extension-collaboration-cursor — remote cursors/selections,
    • standard extensions for headings, lists, tables, code blocks, images, links, task lists.
  • Document schema is the source of truth and is defined centrally in packages/shared (node/mark specs), so that editor, server-side rendering/export, and plugin validation agree on what a valid document is.
  • Markdown interop: paste and import/export convert between Markdown and the ProseMirror document model (prosemirror-markdown, extended for our custom nodes such as wikilinks). Markdown remains the primary exchange format; the internal format is the ProseMirror/Yjs document, as the vision allows ("internal format follows technical requirements").
  • Links: a bubble menu on links offers "edit URL" and "open in new tab" (the two actions required by the vision).
  • Images: clipboard paste and menu insert both upload through the API (quota-checked, ADR 0011) and insert an image node referencing the stored file — no base64 blobs inside documents.
  • Wikilinks: a custom inline node wikilink with [[ autocomplete, resolved against pages of the current pond; backlinks are indexed server-side (see data-model.md).

Consequences

  • ProseMirror's schema-based model gives us structural guarantees (valid documents by construction) that plain contenteditable or Markdown-string editors cannot.
  • Plugin-defined block types register as ProseMirror nodes rendered inside a sandbox (details in plugin-architecture.md).
  • Mobile editing is explicitly out of scope (kickoff decision); we target desktop browsers and accept degraded editing UX on touch devices, while reading stays fully responsive.

Alternatives considered

  • Slate, Lexical: capable editors, but Yjs integration and the extension ecosystem are notably less mature than ProseMirror/TipTap's.
  • CodeMirror + Markdown source editing: excellent for developer wikis but contradicts the WYSIWYG requirement.
  • BlockNote (block editor on TipTap): attractive UX shortcut, but its opinionated block model would constrain our plugin block types and styling requirements; we build on TipTap directly.