My blog runs on a custom TipTap editor. For months it covered the basics well — headings, code blocks with syntax highlighting, tables, Mermaid diagrams — but every time I wanted to flag something important, hide a long aside, or let a reader zoom into a dense diagram, I hit a wall. So I rebuilt the editor's block system and fixed the renderer gaps I found along the way. This post is written with the new blocks themselves — what you're reading is the demo.
Callout blocks: say the important thing loudly
Documentation-style callouts — info, tip, warning, danger — are the fastest way to pull a reader's eye to what matters. They didn't exist in my editor, so I built a CalloutExtension as a proper TipTap node with a variant attribute, a React NodeView with a variant picker, and matching renderer styles:
Tip: callouts are block nodes (content: 'block+'), so they can hold paragraphs, lists, even code — not just a single line of text.
The variant picker lives in the node view header, so I can flip a callout from info to warning without touching the content. Small detail, big authoring win.
Warning: a callout is only as good as its restraint. If every paragraph is highlighted, nothing is. I try to keep it to one or two per article.
Collapsible details blocks: hide the long asides
Some explanations deserve to exist without demanding attention — implementation notes, alternative approaches, the "actually, here's why" paragraphs. The new detailsBlock node renders as a native <details> element. Expand the one below for the design notes on this very block:
▶How the Details node view works
The DetailsExtension stores two attributes: summary (the clickable header text) and open (whether it starts expanded). The NodeView renders a real <details> element, so collapsing works with zero JavaScript on the published page — progressive enhancement for free. Double-clicking the summary in the editor lets me rename it inline.
On the rendering side, mdx.tsx maps detailsBlock straight to <details>/<summary>, styled with a subtle border and a rotating chevron. No hydration tricks, no client component needed.
Diagrams readers can actually explore
Mermaid diagrams were already supported, but dense ones — sequence diagrams with a dozen participants — rendered at whatever size fit the column, and readers were stuck squinting. The new MermaidViewer ships a floating control toolbar on every diagram:
Zoom in / out, from 0.5x to 4x
Drag to pan once zoomed
One-click reset
Fullscreen mode (Esc to close)
Try it on this architecture diagram — zoom in and drag around:
The renderer gap nobody noticed
While wiring up the new blocks I audited every node type the editor can produce against every case the renderer handles. The audit caught a real bug: the editor had an internalLink node (for linking between posts and projects), but mdx.tsx had no case for it — so internal links silently vanished from published articles. Authors saw them in the editor; readers never did.
Danger: a renderer that drops unknown nodes silently is a content-integrity bug. Every node the editor can emit must have a render path, or at minimum a visible fallback — never silent disappearance.
What's next
▶Roadmap: footnotes, math, and richer embeds
Still on the list: footnotes with back-references, KaTeX math rendering, and one-click embeds for X posts and GitHub repos. The pattern is established now — extension, node view, toolbar entry, renderer case, audit — so each new block is a day's work, not a week's.
If you write with a custom editor, audit your renderer against your node list today. You might find your own vanishing links.
