Contentful lets you replace the UI of a Rich Text field with your own App. That sounds like a front-end job — build a nicer editor, mount it in the field location, done.

It isn't. The editor UI is the easy 20%. The hard 80% is a small file most people never think about: the layer that converts between your editor's internal model and Contentful's stored document — losslessly, in both directions.

I built one on top of PlateJS (which is a Slate editor underneath), and this post is about that conversion layer — the part that actually decides whether the whole thing works.

Two models that don't match

Contentful Rich Text is a fixed JSON schema (@contentful/rich-text-types): a document whose content is a tree of blocks, inlines and text nodes, where formatting lives on text nodes as an array of marks: