Micheal Cunningham.Software developer & AI engineerLet’s talk
← All articles

Custom components

A document can be a working part of your application

Rich text is only one part of an application editor. Records, variables, review, recovery, and export shape the complete experience.

Think beyond the typing surface

A business document usually exists for a reason. It might describe a project, record an agreement, explain a procedure, or communicate a decision. That purpose connects it to the rest of the application.

The authoring work I care about brings those connections into the editor. A document can belong to a customer, use information from a project, move through review, and remain accessible from the relevant workspace.

This changes the design questions. Formatting still matters, but so do ownership, relationships, document state, and the path from a draft to something another person can rely on. I want the editor to support that whole journey.

Give content an intentional structure

An application editor needs a content model that can represent the things people actually write. Paragraphs, headings, lists, and tables are a starting point. Particular workflows may need structured variables, references, diagrams, signatures, or specialized blocks.

My document work includes the Tiptap and ProseMirror ecosystem. The broader design principle is to make supported content explicit and give each extension a clear purpose. A specialized block should have defined editing behavior, validation, and a sensible representation when exported.

I also want the toolbar to reflect the current selection. A table offers different actions from a paragraph. A selected variable should explain what it represents. That attention makes a powerful editor understandable without requiring every command to be visible all the time.

Be precise about connected values

A live variable looks simple on the page: customer name, project title, renewal date. Underneath, it raises a consequential question. Should an existing document change when the underlying record changes?

For a working draft, a current value may be exactly what the author wants. For an approved agreement or historical report, preserving the reviewed value may be essential. The application needs an explicit rule for that transition.

I would make the behavior visible to the author. A draft can identify a connected value and its source. A finalized version can preserve a stable representation according to the workflow's requirements. An unavailable or unauthorized source should produce a clear state instead of quietly substituting misleading text.

The right behavior comes from the document's business purpose.

A REFERENCE HAS IDENTITY
  1. Customer UUID
  2. Structured editor node
  3. Rendered customer reference
  4. Explicit export representation
CustomerReference {
  customerId: UUID
  label: string
}

// Display text is not the record identity.

Illustrative document model. Keeping identity separate from a displayed name makes linked content understandable when a record is renamed.

Protect the work in progress

An editor asks people to invest time and attention. Saving behavior therefore deserves as much design work as formatting.

The interface should distinguish changes waiting to save, changes successfully saved, and a failed save that needs attention. If the network disappears, the user needs a truthful explanation of what is safe and what still needs recovery.

Concurrent editing adds another layer. The system needs a deliberate approach to versions, conflicts, or collaborative editing. A silent last-write-wins overwrite can destroy useful work even when both save requests technically succeed.

Undo, recovery, and review also need clear boundaries. Undoing an edit is a different action from reverting an approved document version. A well-designed editor makes those distinctions understandable without exposing its internal machinery everywhere.

Treat export as part of the product

A document may look excellent in the browser and still produce an unusable PDF. Tables can run off a page, headings can become stranded, and branding can shift. Imported documents can introduce their own surprises.

I treat export and import as their own product surfaces. They need representative content: long tables, page breaks, headers, footnotes, and the specialized blocks the editor supports. The exported result should be checked against what the user intends to share.

My practical takeaway is to choose one real document and follow it from creation through editing, saving, review, and delivery. That exposes the requirements a toolbar alone cannot reveal. A strong application editor gives the document a dependable place in the business process as well as a good place to write.

KEEP READINGMake the next change easier to trust ↗

Something you want to build?

Let’s work through it.

Work directly with me on the architecture, the application, and the details that make it useful.