Email Editor
@markrelay/email-editor is the block-based email editor that powers MarkRelay campaigns and templates — a Notion-style editing experience that produces a portable JSON document instead of fragile HTML.
Features
- Email-native blocks — sections, multi-column layout, buttons, images (upload or URL), inline images and brand icons, logo, spacer, divider, footer, and a raw-HTML escape hatch.
- Rich text — headings, lists, blockquotes, syntax-highlighted code blocks, alignment, colors, links with previews.
- Variables —
{{ firstName }}placeholders with fallbacks, substituted at render/send time. Perfect for personalization and agent-generated campaigns. - Slash commands — type
/for a searchable block palette; drag handles and bubble menus for direct manipulation.
Quick start
import {
EmailDocumentSchema,
EmailEditor,
type EmailDocument,
} from "@markrelay/email-editor";
import { useState } from "react";
export function Compose() {
const [doc, setDoc] = useState<EmailDocument>(() =>
EmailDocumentSchema.parse({
type: "doc",
content: [{ type: "paragraph" }],
}),
);
return (
<EmailEditor
value={doc}
documentKey="compose"
onChange={setDoc}
uploadImage={async (file) => uploadAndGetUrl(file)}
variables={[{ name: "firstName" }, { name: "unsubscribeUrl" }]}
/>
);
}Design principles
- EmailDocument is the source of truth. It is a versioned, validated JSON tree: store it, diff it, generate it with an LLM, edit it again later — including its semantic theme snapshot at
theme— then render at send time with @markrelay/email-render. - No server coupling. You own image upload, persistence, and rendering; the editor is a controlled React component with a handful of props.
- Email reality first. Blocks are restricted to what actually works across Gmail, Outlook, and Apple Mail — the renderer emits table-based, inline-styled HTML.
Full prop reference lives in the package README (packages/email-editor). Available to Source License customers as workspace packages — see pricing.