# BlockNote to Email-Safe HTML Exporter
## Overview
Messages uses [BlockNote](https://www.blocknotejs.org/) as its rich-text editor.
BlockNote's built-in `blocksToHTMLLossy` produces HTML that relies on CSS classes
and modern layout which email clients strip or ignore.
The **EmailExporter** converts BlockNote's block tree into HTML that is safe for
email rendering: every style is **inline**, images reference **cid:** URLs for
MIME embedding, and layout is achieved through `
`
wrappers generated by [@react-email/components](https://react.email/).
```
src/frontend/src/features/blocknote/email-exporter/
├── index.tsx # Exporter implementation
└── index.test.tsx # Test suite
```
## Architecture
### Conversion pipeline
```
BlockNote blocks (JSON)
│
▼
transformBlocks() ← Groups consecutive list items, recurses children
│
▼
React nodes ← Using @react-email/components (Section, Text, Img…)
│
▼
renderToStaticMarkup() ← react-dom/server, no hydration markers
│
▼
Email-safe HTML string
```
### Public API
```ts
import { EmailExporter } from '@/features/blocknote/email-exporter';
const exporter = new EmailExporter();
const html = exporter.exportBlocks(
blocks, // BlockNote document blocks
editorDomElement, // Editor DOM element (for image width fallback), nullable
);
```
### Integration points
| Caller | File | Notes |
|--------|------|-------|
| Message send | `message-composer/index.tsx` via `exportContent()` ref | Called at send time, not on every keystroke |
| Signature editor | `hooks/use-base64-composer.tsx` | Object URLs resolved to base64 after export |
| Template editor | `hooks/use-base64-composer.tsx` | Same hook, shared with signatures |
Export is intentionally **deferred to send/save time** to avoid the cost of
`blocksToMarkdownLossy()` (which creates real DOM elements) on every keystroke.
## Supported blocks
### Content blocks
| BlockNote type | HTML output | Styling |
|---|---|---|
| `paragraph` | `` (via ``) | textAlignment, textColor, backgroundColor |
| `heading` | `