Courier's customers needed a visual message editor they could embed in their own products. Their users would create and edit messages without leaving those applications, using Courier's messaging infrastructure and document format.

I was the first engineer working on the embeddable designer. I clarified requirements, chose the initial stack, designed the architecture, and built most of the early version. Other engineers joined later, and we continued developing and maintaining the product together. The public repository records that work.

I chose TipTap and ProseMirror so I could get the editor working sooner. Building our own rich text editor would have given us more control over its features and behavior, but also much more implementation work. With TipTap, I had to build our product-specific features around another library's document model and extension points.

A library inside another product

The editor had to fit into an application I did not control. An integrating product could open several templates, manage its own persistence, or update content from outside the editor. Those requirements shaped the boundary between the library and its host.

As the designer developed, I moved shared editor state into a separate store for each instance. I also corrected a feedback loop between externally supplied content, internal editor state, and change callbacks. External synchronization had to remain distinct from a user's edit.

The resulting boundary let a host application supply content without repeatedly receiving the same change back, while separate stores kept each editor's template state independent. The instance isolation change and the controlled-state correction record those implementations.

Preserving the document through editing

The editor's internal document and Courier's Elemental format represented content differently. Using the existing editor meant maintaining conversion code in both directions. It needed to retain formatting, links, variables, and translations, including data that was not visible in the current editing view.

I developed the conversion functions and added locale preservation in both directions. I later fixed a case where a full conversion cycle lost translations in list items. The fix retained those translations through the editing representation and back into Elemental, with regression tests for that path.

The locale-preservation change and the list-item correction show the conversion work. A user editing the visible text should not silently lose a translation elsewhere in the document.

Saving also had to read the latest edit. A user could see fresh text while a request still read an older document. I changed the save flow to retain content arriving during a save, then added a step to apply pending editor updates before reading the document. Regression tests covered those timing scenarios.

Checking beyond the canvas

The document's next step was Courier's backend renderer. A correct-looking editor and valid JSON did not establish that the rendered message would preserve the same content. I added full-cycle tests that edited a template, produced Elemental, submitted it to the Courier API, and checked the returned HTML.

The suite combined semantic assertions with visual comparisons. It gave us a way to check formatting and content after server processing, rather than stopping at the editor's own representation. The test implementation records that verification path.

I worked on the SDK rather than Courier's document format or backend renderer. The linked tests cover specific conversion, editing, and rendering scenarios; they do not establish compatibility with every document or email client, or a guarantee against every save failure. The full-cycle suite is evidence of a verification approach, not a claim that it runs on every pull request.