Document Model
The document is a plain JSON object. You can store it in any database, serialize it, or manipulate it programmatically.
EmailDocument
interface EmailDocument {
type: 'email';
settings: EmailDocumentSettings;
sections: EmailSection[];
}Settings
interface EmailDocumentSettings {
// Layout
contentWidth: number; // Default: 640
contentAlign: string; // Default: 'center'
paddingTop: number; // Default: 32
paddingBottom: number; // Default: 32
paddingLeft: number; // Default: 16
paddingRight: number; // Default: 16
marginTop: number;
marginBottom: number;
// Typography
fontFamily: string; // Default: "'Inter', 'Helvetica Neue', Arial, sans-serif"
fontWeight: number; // Default: 400
fontSize: number; // Default: 16
// Colors
backgroundColor: string; // Default: '#f5f5f4'
contentBackgroundColor: string; // Default: '#ffffff'
bodyTextColor: string; // Default: '#1f2937'
linkColor: string; // Default: '#2563eb'
linkUnderline: boolean; // Default: true
// Extras
preheaderText: string;
colorPalette: ColorPalette;
customColors: CustomColor[];
}Sections
Each section is a horizontal row in the document. Sections contain one or more columns.
interface EmailSection {
id: string;
columns: EmailColumn[];
backgroundColor: string;
paddingTop: number;
paddingBottom: number;
paddingLeft: number;
paddingRight: number;
marginTop: number;
marginBottom: number;
borderTopWidth: number;
borderBottomWidth: number;
borderLeftWidth: number;
borderRightWidth: number;
borderColor: string;
borderStyle: string;
}Columns
Each column has a width (as a percentage string) and an array of blocks.
interface EmailColumn {
id: string;
width: string; // e.g. '100%', '50%', '33.33%'
blocks: EmailBlock[];
}Creating Documents
import { createEmptyDocument, createLegacyHtmlDocument } from 'block-based';
// Empty document with a default hero section
const doc = createEmptyDocument();
// Wrap existing raw HTML in a document
const legacy = createLegacyHtmlDocument('<h1>Hello</h1>');Normalizing Documents
If you load a document from storage that may be missing fields (e.g., saved with an older version),
use normalizeDocument() to fill in defaults:
import { normalizeDocument } from 'block-based';
const doc = normalizeDocument(rawJsonFromDatabase);Type Guard
import { isEmailDocument } from 'block-based';
if (isEmailDocument(value)) {
// value is EmailDocument
}