MindooDB Blog

Mindoo TeamEdit update - collaborative Word/.docx editing on MindooDB Haven

Karsten Lehmann 25 May 2026 12:30:00

Two people open the same Word document. One of them is writing the introduction. The other is reshaping the table in section three and pasting in a screenshot from a meeting. They are on different laptops, sometimes on different networks, sometimes one of them on a phone. Nobody is calling out cell coordinates over Slack. Nobody is renaming the file v3-FINAL-final-karsten.docx. They just type, and the document keeps converging.

That is the new feature in Mindoo TeamEdit today: a collaborative Word/.docx editor, sitting next to the markdown editor we shipped in April and using the same MindooDB collaboration machinery underneath. The same TeamEdit can now also keep more than one document open at once - a Window menu in the menu bar lists every open document, so the markdown brief that started a project, the docx memo it is turning into, and a quick scratch document can live together in the same TeamEdit and you simply flip between them from the menu.

Here is a short video of two TeamEdit instances editing the same docx file in parallel on the same Haven workspace page. Both panes are real editors, both are saving back through MindooDB, and the merge happens automatically:

The clip walks through the cases that tend to break the worst in office editors: two people typing into the same paragraph, two people applying conflicting formatting, an image dropped into the right pane while a table is being inserted on the left, and - because this is MindooDB - a quick trip back into application time travel to see what the same document looked like a few minutes earlier. Comments and comment replies are part of the same merge story; we left them out of this clip because the narrow side-by-side layout did not give them enough room to read well on screen. They work exactly the way you would expect from the rest of TeamEdit: write a comment, reply, resolve, and the threads sync across every connected client like any other document content.

Why we did not write the docx editor ourselves

A docx file is not really “Word text with some formatting on top”. It is Office Open XML (OOXML): a zipped bundle of XML parts describing styles, numbering, headers and footers, sections, fonts, tables with merged cells and percentage widths, paragraph properties, tracked changes, comments with anchored ranges, drawings with positioned shapes, inline and floating images with text wrap, equations, footnotes, endnotes - and a long tail of things every real-world document tends to hit eventually. Rendering that in the browser at a fidelity that does not embarrass the author the moment the file goes back to Word is a serious undertaking. Replicating it badly is worse than not doing it at all, because then every roundtrip silently corrupts the file.

So the plan from the start was to pick a docx editor that does the OOXML side well and bolt the MindooDB collaboration model onto it, not the other way around. Over the last few weeks we ran every major candidate we could find through the same evaluation - checked it against our test dataset for OOXML fidelity, looked at the licensing terms, and worked out what it would take to drive concurrent edits through the MindooDB sync layer rather than through a vendor’s own merge server.

SyncFusion Document Editor. A capable, well-funded commercial editor with real concurrent editing support and an attractive free Community Licence for small companies, which makes the entry barrier genuinely low. Two structural choices made it the wrong fit for us anyway. First, the editor’s internal data format is not OOXML but a custom JSON shape called SFDT, and the conversion between .docx and SFDT is a server-side operation backed by SyncFusion’s own document conversion library. Second, the concurrent editing path is Operational Transformation (OT) against a SyncFusion document server, also server-side. Both of those collide head-on with what MindooDB is: an local-first, end-to-end encrypted store where the server only ever sees ciphertext and the merge engine is Automerge running in the browser. Putting SyncFusion’s server in the path would have meant a second backend that has to see the plaintext document, a second auth model, and a merge model (OT) that does not match the CRDT model the rest of MindooDB is built around. Even with the free Community Licence, that is too much architecture to assimilate.

Apryse WebViewer. Commercial, negotiated per-user pricing, and the closest match to our preferred shape on paper - the editor operates directly on OOXML, so the file format you see on disk is the file format the editor reasons about. It also has an excellent rendering and annotation story for PDF and docx. The catch came when we looked closely at collaborative editing of the document body: their concurrent editing support today is built around annotations on PDF/docx (comments, highlights, redactions), not around two people typing into the same paragraph and merging the underlying text. For an annotator-heavy workflow this is fine; for an editor where the prose itself is being co-authored it is a clear gap. Combined with per-user commercial pricing for a sample app that we ship as Apache 2.0 source, it was not the match.

EigenPal docx-editor. Free and open source under Apache 2.0, with a commercial company (EigenPal) behind it that is actively shipping releases (the 1.0 release landed on 19 May 2026, splitting the previous monolithic package into a framework-agnostic core plus React and Vue adapters and an agent toolkit), a growing developer community, and - importantly for us - a ProseMirror foundation. Round-trip fidelity against our test documents was already good: tables, fonts, embedded images, tracked changes, comments, headers, footers and section breaks survived the trip both ways. Because it is open source we can read the parser, fix things ourselves when we run into a case nobody else has hit yet, and contribute fixes back rather than depending on a vendor’s roadmap. And because the editor is built on ProseMirror, the document is already structured as a node tree we can plug a different storage adapter into - which is exactly what we needed for hooking up MindooDB.

The full evaluation matrix had a few more entries on it (we also looked at OnlyOffice, Collabora Online, and a small Apache 2.0 library that turned out to be too thin to cover real documents), but the three above are the ones that made the final shortlist. EigenPal won on the combination of license, source availability, fidelity, and how cleanly the storage layer could be replaced. We are very happy with that choice; we are also keeping a close eye on the others, and there is nothing in TeamEdit’s design that would prevent us from swapping the editor later if the picture changes.

How concurrent editing actually works under the hood

Underneath the editor, every TeamEdit document - markdown or docx - is a MindooDB document, which means an Automerge CRDT, signed, encrypted, and synced through the same machinery as everything else in MindooDB Haven. The interesting question is what shape the rich text takes inside that Automerge document. Plain text is easy; rich text is the genuinely hard problem.

The answer is the Automerge rich text representation - originally described in Peritext and shipped as a first-class Automerge feature in Automerge 2.2. Instead of storing a tree (paragraphs containing runs containing characters), the document is stored as a flat sequence of characters annotated with two kinds of markers:

  • Formatting spans with a begin, an end, a marker type (bold, italic, font:Calibri, color:#000000, …), and an “expand at boundary” flag that decides whether new characters typed at the edge of the span inherit the formatting. A character can be inside many overlapping spans - the same word can be bold and italic and part of a footnote anchor.
  • Block markers for paragraphs, headings, list items, table rows, table cells, and so on. A block marker has a type and a parent chain, and a character belongs to exactly one block at a time (a sentence can be bold or italic, but it cannot simultaneously live in two paragraphs).

This shape is dramatically friendlier to a CRDT merge than a literal tree would be. Two users typing into the same paragraph produce inserts into the same text sequence with stable positions, which Automerge interleaves without conflict. Two users formatting overlapping ranges produce two formatting spans that simply coexist. Two users restructuring the same list produce block-marker edits that compose rather than fight - a case where naive tree-based approaches tend to lose entire list items, as the Automerge 2.2 announcement shows in some painfully concrete examples. We picked this representation precisely because it survives the worst cases.

The bridge between EigenPal’s ProseMirror document and this Automerge rich text representation runs in the editor: on the way out (local edit applied), it converts a ProseMirror transaction into a small set of operations on the Automerge text sequence and its spans; on the way in (remote change synced), it diffs the rebuilt Automerge document against the current ProseMirror state and replays the change as a ProseMirror transaction so the editor’s selection, decorations and history all keep working. The starter scaffolding for that mapping is the automerge-prosemirror project from the Automerge team, which we hardened around the ProseMirror schema EigenPal actually uses for docx (tables, comments, tracked changes, images, footnotes). Doing this inside the editor rather than at the document boundary is what keeps the wire payload small: the moment a character is typed, MindooDB has a precise span-level delta to sync, not a whole-document snapshot.

The sync itself is plain MindooDB sync. Automerge documents in MindooDB sync incrementally - each peer maintains the heads of the document it has seen, and the wire protocol exchanges only the operations the other side does not have yet. For rich text in particular this is a big deal: editing one paragraph in a long document sends the operations for that paragraph, not the whole document. Embedded images are part of the Word document content in this mode, so inserting one is synced as a document change rather than as a separate MindooDB attachment. Rebuild a table? Block-marker changes for the rows that moved, plus the inserts and deletes for the cells whose content actually changed, plus nothing for everything that stayed put. The result is concurrent editing that stays cheap even on patchy connections.

A note on the transport between TeamEdit and Haven, because the docx mode diverges from the rest of TeamEdit here. The markdown editor sends its changes to Haven as small SDK patches and leaves the Automerge runtime on Haven’s side; the docx editor instead keeps its own Automerge document in the browser tab next to the editor and syncs it with Haven through Automerge’s native sync protocol. We initially tried the SDK-patch shape for docx too, but the merge quality on fully-formatted documents was not where we wanted it, so we let the app hold the Automerge runtime locally for this mode and let the two Automerge engines talk to each other directly. The wire is still end-to-end encrypted, the document on Haven’s side is still the canonical signed history, and the merge results are the ones Automerge produces - the only thing that moved is where the runtime lives.

What the video actually shows

The clip embedded above starts with the two TeamEdit instances side by side on the same Haven workspace page, both pointed at the same docx document.

We start with parallel text writing: both panes type into the same paragraph and into nearby paragraphs at the same time. Every insert appears on the other side once the next sync lands; nothing is overwritten and nothing scrolls out of view. The behaviour is the same whether the two windows are in the same browser, in two browsers on the same machine, or on two different machines.

The next stretch covers formatting: bolding, italicising, changing the font and font size of overlapping ranges, applying highlight colours. Because formatting is a span over the text sequence, two overlapping bolds simply coexist; two different colours applied to overlapping ranges produce overlapping spans that the editor renders cleanly. No formatting is lost when both sides format the same word at the same time.

We then walk through images and tables. An image is dropped into the document on the right while the left pane is inserting a new table further up; the image becomes part of the Word document content, the new table appears in the merged result with the cells the author typed into, and neither side overwrites the other’s structural change. Tables and inline images are the places where naive editors tend to lose data in concurrent edits - the table inserted on one side disappears because the other side’s block edit “wins”, or the image is dropped because the surrounding paragraph was renumbered - and the whole point of mapping to Automerge’s rich text representation is that both edits land cleanly against the same baseline.

The clip closes with a trip into time travel. One of the two windows is switched to a duplicate application registration pinned to a moment a few minutes earlier; the same document appears in the same editor, read-only, exactly as it looked at that point. The point of including this beat in the video is to underline that the docx editor itself does not need any time travel code - the connector below it serves the historical revision, and the editor renders it as plain content. Comments, tracked changes, embedded images: all see the past consistently.

Beyond what the video shows, TeamEdit’s docx mode also supports import of an existing .docx from disk into the active document, export of the current document back to a downloadable .docx ready to send to anyone outside MindooDB, and printing through the browser print dialog (which on most systems doubles as “Save as PDF”). All three are wired through the EigenPal editor’s own pipelines, so the OOXML on the way out matches the OOXML on the way in.

The one MindooDB-native feature we deliberately did not try to squeeze into the same recording is comments and replies. Threaded comments anchored to ranges in the text are a first-class part of the EigenPal editor and a first-class part of the Automerge rich text representation, and they merge across collaborators just like the text content does (add, reply, resolve, delete, all CRDT-safe). They are not in this clip simply because the narrow side-by-side layout did not give them enough room.

Multiple documents open at the same time

Adding the docx editor was a good moment to also fix something that had quietly been a friction point in TeamEdit since day one: the editor could only have a single document open at a time. With markdown plus docx in the same tool, and with most real workflows touching more than one file in a single session, that was no longer acceptable.

TeamEdit now keeps any number of documents open in parallel and exposes them through a classic Window menu in the menu bar - the same model TeamGrid uses for its open workbooks. Open another document via File / Open or File / New and it becomes a new entry in the Window menu; click an entry to switch to that document. The active document is marked with a check mark, an asterisk indicates that the document has unsaved changes, and a small icon distinguishes Word documents from Markdown documents at a glance. At the bottom of the menu sits a Close current document entry that tears the active document down cleanly. Each open document carries its own undo history, its own scroll position, its own editor instance, and - for collaboratively edited ones - its own live sync subscription, so a markdown brief and a docx memo stay independently live at the same time.

The two editor modes share as much surrounding chrome as they reasonably can - the menu bar, the file menu, the title bar, the document properties dialog, the comments panel, the revision picker, the share/export entry points - but the editor surface itself is whatever the document needs: Milkdown / Crepe for markdown documents, the EigenPal docx editor for Word documents. Picking which one opens is automatic from the document’s content type, and a new document can be created in either mode through File / New.

How to get it

If TeamEdit is already registered in your Haven, it updates itself the next time you launch it; the registration stays the same. If it is not, the fastest way is to open the Applications screen, press New, and pick TeamEdit from the example presets. One click registers the app, picks a database, and opens an empty workbench with a fresh markdown document already loaded. From the File menu you can then create a new Word document, import an existing .docx file from disk, or open one that is already in the database, and the Window menu lets you flip between everything you have opened in this TeamEdit.

The source code is on GitHub and is intentionally readable rather than feature-complete, so it doubles as a tutorial for building Haven apps that need real collaborative editing on top of the EigenPal docx-editor and Automerge:

https://github.com/klehmann/mindoodb-app-teamedit

The SDK’s patch APIs - field-level set/unset, the granular JSON patch API that powers TeamGrid, and the granular text patch API behind TeamEdit’s markdown mode - sit on top of the same Automerge engine and the same encrypted sync that the docx mode rides natively here. More details are in the SDK README.

A short note on what we expect to evolve next. The docx editor itself will keep getting better as EigenPal ships new releases - that is a large part of why we picked an actively maintained open source project rather than a frozen library. On our side, the ProseMirror-to-Automerge bridge will keep getting hardened against the long tail of real-world OOXML constructs people send each other in production. And then there is the bigger story we hinted at in the TeamGrid launch and that this post is really another step in: editing Office formats - Word now, more to follow - in a data-sovereign way, with full concurrency and offline support, without sending the document to anybody else’s server. The .docx editing flow you just watched in the video runs entirely between two TeamEdit instances on the same Haven workspace page and the encrypted MindooDB store underneath them. We think that is the right shape for an Office editing experience.