If you’ve ever wrestled with WordPress email — patching together plugins, fighting Outlook rendering bugs, or explaining to a client why their transactional mail looks nothing like the design — you know the frustration. I got fed up.
So I built my own solution: cubicFUSION Email Builder, a drag-and-drop email editor living right inside the WordPress admin. No compromises, no workarounds. Just the setup I always needed, surely over-engineered ;) Built on @usewaypoint/email-builder-js with cubicFUSION-specific extensions and deep changes.
Release planned? Not sure yet. Internal use mostly and for my clients. If interested, get in touch.
























The editor is split into three panels:
- Samples drawer (left) — block palette and starter templates
- Canvas (centre) — live editable email layout with dot-grid backdrop
- Inspector (right) — settings for the selected block or global email options, grouped into collapsible accordion sections
Canvas backdrop
The grey area outside the email body shows a subtle radial-gradient dot pattern, giving the canvas a design-tool feel and making the email boundary clearly visible. The pattern is editor-only and does not appear in rendered HTML or MJML output.
Inspector sections

Every inspector panel is organised into collapsible accordion sections — typically Content, Style, Typography, Layout, and Spacing. All sections start collapsed; expand only what you need.
An Expand all / Collapse all control appears in the panel header. Expanded/collapsed state is persisted per panel type in localStorage, so your layout preferences survive page reloads and block switches (e.g. expanding “Style” in the Button inspector is remembered independently from the Heading inspector).
Three additional sections appear below every block panel:
Section | Contents |
|---|---|
CSS class | Optional class name targetable via Custom CSS in the Settings tab |
Visibility | Hide on mobile (<600 px) / Hide on desktop (≥600 px) toggles |
Condition (Twig) | Wraps the block in {% if … %}{% endif %} at send time when set |
The Settings tab panel is also divided into sections: Content (preheader text), Custom CSS, and Delivery (CAN-SPAM check, unsubscribe URL override, physical address override).
Color pickers
Every color field shows the current hex value in an editable monospace text field next to the color swatch. You can type a 6-character hex value directly (#RRGGBB) — the swatch and picker update live. The full picker (with hue/saturation gradient, brand swatches, and preset palette) is still available by clicking the swatch.
Unsaved changes
The Save button shows an orange dot badge whenever the document or template name has unsaved changes. Cmd+S (macOS) / Ctrl+S (Windows/Linux) triggers the save from anywhere in the editor, including while a text field is focused.
Block Reference

Container
The root-level section wrapper. Every section of an email must be inside a Container. Containers stack vertically from top to bottom.
Setting | Options / Range |
|---|---|
Background color | Color picker (nullable) |
Border color | Color picker (nullable) |
Border radius | 0–48 px (step 4) |
Padding | Top / Right / Bottom / Left (px) |
Background image URL | Text field + WP Media Library picker |
Background size | Cover / Contain / Auto (shown when image is set) |
Background repeat | None / Repeat / Repeat-X / Repeat-Y (shown when image is set) |
Background position | Text field, e.g. center center (shown when image is set) |
Columns
A 2- or 3-column horizontal layout. Must be placed inside a Container. Each column is an independent content slot that accepts any block.
Setting | Options / Range |
|---|---|
Number of columns | 2 or 3 |
Fixed column widths | Per-column pixel width overrides (optional; auto-distributes if unset) |
Columns gap | 0–80 px (step 4) |
Vertical alignment | Top / Middle / Bottom |
Stack on mobile | Toggle — injects @media CSS to stack columns vertically at narrow viewports |
Background color | Color picker (nullable) |
Padding | Top / Right / Bottom / Left (px) |
Heading
A single-line heading rendered as <h1>, <h2>, or <h3>.
Setting | Options / Range |
|---|---|
Content | Text field |
Level | H1 / H2 / H3 |
Text color | Color picker (nullable) |
Background color | Color picker (nullable) |
Font family | Global inherit / Modern Sans / Monospace / Serif / etc. |
Font weight | Normal / Bold / Light (100–900) |
Text alignment | Left / Centre / Right |
Padding | Top / Right / Bottom / Left (px) |
Text
A paragraph block with three rendering modes, selectable per block in the inspector.
Setting | Options / Range |
|---|---|
Content | Multiline text field |
Render as HTML | |
Markdown | Toggle — renders GitHub-Flavored Markdown: **bold**, *italic*, [link](url), lists, tables, and inline HTML passthrough. |
Text color | Color picker (nullable) |
Background color | Color picker (nullable) |
Font family | Global inherit / Modern Sans / Monospace / Serif / etc. |
Font size | Dropdown (10–48 px) |
Font weight | Normal / Bold / Light (100–900) |
Text alignment | Left / Centre / Right |
Padding | Top / Right / Bottom / Left (px) |
Rich Text
A fully inline-editable block. Click into the block in the canvas to edit; a formatting toolbar appears for bold, italic, underline, links, ordered/unordered lists, and alignment.
Setting | Options / Range |
|---|---|
Background color | Color picker (nullable) |
Padding | Top / Right / Bottom / Left (px) |
(All text formatting is applied directly in the canvas via the inline toolbar.)
Image
A responsive image block.
Setting | Options / Range |
|---|---|
Source URL | Text field + WP Media Library picker |
Alt text | Text field |
Click-through URL | |
Width | px or % value |
Height | px value (optional) |
Alignment | Top / Middle / Bottom |
Background color | Color picker (nullable) |
Text alignment | Left / Centre / Right (affects inline alignment) |
Padding | Top / Right / Bottom / Left (px) |
Media Library — the picker button opens the native WordPress Media Library modal. Selecting an image fills the URL automatically and pre-fills alt text from the attachment metadata if the field is empty.
Button
A CTA button rendered as a full HTML <a> tag styled as a button (compatible with Outlook via VML fallback in the underlying renderer).
Setting | Options / Range |
|---|---|
Text | Label text |
URL | Destination href |
Width | Full-width / Auto |
Size | Xs / Sm / Md / Lg |
Shape preset | Rectangle / Rounded / Pill |
Border radius | 0–40 px — fine-tunes or overrides the shape preset |
Text color | Color picker |
Button color | Background color picker |
Background color | Wrapper background color picker (nullable) |
Font family | Global inherit / override |
Font size | Dropdown |
Font weight | Normal / Bold / etc. |
Text alignment | Left / Centre / Right |
Padding | Top / Right / Bottom / Left (px) |
Divider
A horizontal rule.
Setting | Options / Range |
|---|---|
Color | Line color picker |
Height | 1–24 px |
Background color | Wrapper background color (nullable) |
Padding | Top / Right / Bottom / Left (px) |
Spacer
An invisible block that adds fixed vertical space between sections.
Setting | Options / Range |
|---|---|
Height | 4–128 px (step 4) |
Avatar
A circular, square, or rounded image — typically used for profile photos, author portraits, or logos.
Setting | Options / Range |
|---|---|
Size | 32–256 px (step 3) |
Shape | Circle / Square / Rounded |
Image URL | Text field |
Alt text | Text field |
Text alignment | Left / Centre / Right (positions the avatar horizontally) |
Padding | Top / Right / Bottom / Left (px) |
HTML
Injects raw HTML verbatim into the rendered email. Use for custom components, conditional comments, or anything not covered by the standard blocks.
Setting | Options / Range |
|---|---|
Content | Raw HTML — multiline text field |
Text color | Color picker (nullable) |
Background color | Color picker (nullable) |
Font family | Override |
Font size | Dropdown |
Text alignment | Left / Centre / Right |
Padding | Top / Right / Bottom / Left (px) |
Twig Block
A Twig template block. The content is written directly in the canvas. Rendered at send time using the Twig engine with WordPress context injected automatically.
Setting | Options / Range |
|---|---|
Background color | Color picker (nullable) |
Padding | Top / Right / Bottom / Left (px) |
Built-in variables always available in every Twig block:
Variable | Value |
|---|---|
{{ site.name }} | get_bloginfo('name') |
{{ site.url }} | get_bloginfo('url') |
{{ user.email }} | Current recipient email |
{{ user.display_name }} | Current recipient display name |
{{ date }} | Send date (formatted) |
{{ year }} | Current year |
Additional variables can be injected via the cfeb_twig_context filter or cfeb-twig-context.php.
Loop Block
Repeats a row template for each item in a Twig array at send time. Define the data source, item variable name, and an optional fallback message for empty arrays. The row template is any arrangement of blocks placed inside the Loop Block in the canvas.
Setting | Options / Range |
|---|---|
Data expression | Twig variable path to iterate, e.g. order.items |
Loop variable | Item variable name used inside the template, e.g. item → {{ item.name }} |
Empty message | Text shown when the array resolves to empty (optional) |
Background color | Color picker (nullable) |
Padding | Top / Right / Bottom / Left (px) |
Social Buttons
A row of social network icon links.
Per-link settings:
Setting | Options |
|---|---|
Platform | Facebook / X (Twitter) / Instagram / LinkedIn / YouTube / TikTok / Pinterest / GitHub / Website |
Color | Override the platform default brand color (nullable — reverts to default) |
Profile URL | Destination href |
Custom icon image URL | Replaces the built-in SVG icon with any image |
Order | Up / down arrows to reorder; × to remove |
Block-level settings:
Setting | Options / Range |
|---|---|
Icon size | 16–64 px (step 4) |
Icon spacing | 0–32 px (step 4) — gap between icons |
Alignment | Left / Centre / Right |
Background color | Color picker (nullable) |
Padding | Top / Right / Bottom / Left (px) |
Global Email Settings

Accessed by clicking anywhere outside a block or via the Global tab in the Inspector. Settings apply to the entire email document.
Setting | Options / Range |
|---|---|
Backdrop color | Outer page background color (default #F5F5F5) |
Canvas color | Email body background (default #FFFFFF) |
Canvas border color | Nullable — adds a border around the content area |
Canvas border radius | 0–48 px — rounds the content area corners |
Font family | Global font applied to all text; override per-block as needed |
Text color | Default text color (default #262626) |
Link color | |
Underline links | Toggle |
Paragraph spacing | 0–48 px — bottom margin on elements |
Body font size | 10–24 px (default 16 px) |
Body line height | 1.0–3.0 × (default 1.5) |
Content width | 400–800 px (default 600 px) |
Body padding | 0–80 px — space between the canvas edge and content |
Brand color palette | Up to 8 saved colors; appear in every color picker in the editor |
Custom CSS | Free-form CSS injected into in the rendered |
Preheader text | Inbox preview text (hidden in email body, visible in inbox list) |
Starter Templates

Three fully designed starters are available from the Samples drawer. Loading a starter replaces the current canvas — save first.
cubicFUSION
Gold #FFD800 on dark #1A1A1A. Sections: brand header (2-col logo + tagline), hero with headline + CTA button, 3-column features grid with icon + label + description, content body, CTA strip, dark footer with unsubscribe and physical address.
Welcome Email
Indigo #4F46E5 / deep violet #312E81. Sections: 2-col header with logo + site name, indigo hero with welcome headline, 3-column “first steps” cards with numbered circle badges, content body, help CTA strip with admin email, dark footer with social icons and CAN-SPAM block.
Transactional
Slate #0F172A / emerald #10B981. Sections: 2-col header, green status banner with ✓ badge, content body, 2-col summary card (label/value pairs), help strip with {#admin_email#}, dark footer with CAN-SPAM block.
All three starters include: {#unsubscribe_url#}, {#site_address#}, {#site_name#}, {#site_url#}, {#admin_email#} tokens.
Code & Preview Panels

The tab bar above the canvas exposes six views.
Editor
Live drag-and-drop canvas. Click a block to select it and edit in the Inspector. Drag blocks from the Samples drawer to add them. The backdrop behind the email body displays a dot-grid pattern (editor-only).
Preview
Rendered HTML in a sandboxed <iframe>. Tokens are substituted with live values from WordPress (get_bloginfo(), etc.). Twig blocks are resolved via a REST call to the PHP renderer. Desktop / Mobile toggle — mobile view constrains the iframe to 370 px wide.
HTML
Full rendered email HTML. Prettier-formatted and syntax-highlighted with the GitHub light theme. Click anywhere in the panel to select all for easy copy. Copy and Download buttons in the header bar.
JSON
Raw editor document JSON (the internal TEditorConfiguration format). Prettier-formatted and syntax-highlighted. Copy and Download buttons.
Plain Text
Editable plain-text version of the email, stored alongside the HTML and sent as the multipart plain-text part. Auto-generate strips HTML tags from the rendered output and fills the field automatically. Character count shown.
MJML
The current document exported as valid MJML XML. Prettier-formatted and syntax-highlighted. Copy copies to clipboard. Download .mjml saves as email.mjml.
MJML Import / Export
Export
The MJML tab converts every block to its MJML equivalent:
Editor block | MJML element |
|---|---|
Container (sole child is a Columns block) | (wrapper skipped — flattened) |
Container (other content) | → single |
Columns | with 2–3 elements |
Heading | |
Text | |
Rich Text | (HTML content preserved) |
Image | |
Button | |
Divider | |
Spacer | |
HTML | |
Social Buttons | + one per link |
Twig Block | |
Loop Block | |
Avatar | (approximation) |
Global settings emit as <mj-head>: <mj-preview> for preheader text, <mj-attributes> for the global font, <mj-style> for custom CSS.
Import
Import MJML in the Samples drawer accepts pasted XML or an uploaded .mjml / .xml file (read via FileReader). The XML is parsed with the browser-native DOMParser — no npm package required.
Conversion rules:
<mj-section>with one<mj-column>→ Container with inline blocks<mj-section>with 2–3 columns → transparent Container wrapping a Columns block<mj-text>containing block-level HTML → HTML block; plain text → Text block<mj-social-element>children → SocialButtons links array<!-- twig: -->comments → Twig blocks;<!-- loop: -->→ Loop blocks- Unknown MJML tags are silently skipped; no crash
Malformed XML or a missing <mjml> root shows an inline error alert; the canvas is not modified.
CFEB-specific fields (
cfebCondition,cfebHideOnMobile,cfebHideOnDesktop) are not represented in MJML and are dropped on export. Import → export does not guarantee a lossless round-trip.
Template Management

From the Email Builder admin list view:
Action | Detail |
|---|---|
New template | Creates a blank template and opens the editor |
Duplicate | Clones the template including document JSON, rendered HTML, plain text, and assignment |
Save | Stores document JSON, re-renders HTML, and stores plain text to post meta |
Import (JSON) | Upload a .json export file from any cubicFUSION instance |
Export (JSON) | Download the full template as a portable JSON file |
Preview | Renders the template with the full pipeline (Twig + tokens) and displays in a modal |
Test email | Sends the rendered template to any address you specify |
Delete | Permanently removes the template post and all associated meta |
Templates are stored as cfeb_template custom posts. Key meta fields:
Meta key | Content |
|---|---|
_cfeb_document | Editor document JSON |
_cfeb_html | Rendered HTML (stored with wp_slash() to survive update_post_meta unslashing) |
_cfeb_plaintext | Plain-text version |
_cfeb_assignment | Context routing assignment JSON |
Automatic Email Wrapping
Hooks into WordPress’s wp_mail filter. When an assignment matches the sending context, the outgoing body is replaced with the fully rendered template HTML. Plain-text is passed through and multipart emails are handled correctly.
Works transparently with:
- WordPress core notifications (new user, password reset, comment notifications, etc.)
- WooCommerce transactional emails
- Contact Form 7, GravityForms, and any plugin calling
wp_mail
Context Routing & Template Assignment
Map a sending plugin slug to a template in Email Settings → Template Assignment.
The plugin slug is auto-detected by walking the call stack — looking for the first frame inside wp-content/plugins/ that isn’t cubicFUSION itself. Override via the cfeb_sending_plugin filter.
Special keys:
default— catch-all fallback when no specific plugin slug matches- Any other key — matched exactly against the detected plugin folder name (e.g.
woocommerce,contact-form-7,give)
Token Substitution
Tokens are replaced in the rendered HTML at send time.
Token | Resolved value |
|---|---|
{#content#} | Original wp_mail message body |
{#subject#} | Email subject line |
{#preheader#} | Inbox preview text |
{#site_name#} | get_bloginfo('name') |
{#site_url#} | get_bloginfo('url') |
{#site_tagline#} | get_bloginfo('description') |
{#admin_email#} | get_bloginfo('admin_email') |
{#unsubscribe_url#} | Supplied via cfeb_unsubscribe_url filter |
{#site_address#} | Supplied via cfeb_site_address filter (CAN-SPAM physical address) |
Twig Templating
Twig blocks and Loop blocks are rendered by the Twig PHP engine at send time. Full Twig syntax is available:
{{ variable }}
{{ variable | upper }}
{{ variable | date('F j, Y') }}
{% if condition %}...{% endif %}
{% for item in items %}{{ item.name }}{% endfor %}
Variables are injected from three sources (merged in order):
- Built-in WordPress context (
site.*,user.*,date,year) - The
cfeb_twig_contextfilter (receives current$mail_args) cfeb-twig-context.phpin the active theme (return an array)
The Preview tab resolves Twig blocks via a REST call, so you can see dynamic output before saving.
UTM Link Decoration
All <a href> links in the rendered HTML are automatically decorated with UTM query parameters before the email is sent. Configurable in global settings:
Parameter | Field |
|---|---|
utm_source | e.g. newsletter |
utm_medium | e.g. email |
utm_campaign | e.g. weekly |
utm_content | e.g. header-cta |
Links containing {#unsubscribe_url#} are excluded automatically (CAN-SPAM compliance).
Delivery Settings
From / Reply-To / BCC
Setting | Effect |
|---|---|
From name | Overrides wp_mail‘s sender name globally |
From email | Overrides wp_mail‘s sender address globally |
Reply-To | Adds a Reply-To header to every outgoing email |
BCC | Blind-copies every email to a fixed address (e.g. archive inbox) |
Subject prefix | String prepended to every email subject line |
Mailer
Option | Configuration fields |
|---|---|
PHP mail() | None — uses server default |
SMTP | Host, port, encryption (None / TLS / SSL), username, password |
SendGrid | API key |
Mailgun | API key, domain |
Amazon SES | AWS Access Key ID, Secret Access Key, region |
Use Test Connection to verify the active mailer without sending a real email. Use Test Email (on any template) to send a fully rendered test to any address.
Email Log
Every outgoing email is recorded automatically.
Column | Value |
|---|---|
Recipient | to address |
Subject | Email subject |
Status | Sent / Failed |
Timestamp | Date + time |
Body | Full rendered HTML (expandable) |
Actions available per entry:
- Resend — re-queues the email for immediate sending
- View — expands the rendered HTML inline
Bulk actions:
- Export CSV — downloads the full log as a
.csvfile - Clear — deletes all log entries
WordPress Media Library Integration
Image blocks and Container background image fields include a media library picker button. Clicking it opens the native WordPress Media Library modal (wp.media). Selecting an attachment:
- Sets the image URL to the full-size attachment URL
- Pre-fills the alt text field from the attachment’s stored alt metadata (Image block only, only if the alt field is currently empty)
Developer Filters
Filter | Signature | Description |
|---|---|---|
cfeb_sending_plugin | (string $slug, array $mail_args): string | Override the auto-detected plugin slug used for template routing |
cfeb_use_template | (bool $use, array $mail_args): bool | Return false to bypass templating entirely for a specific email |
cfeb_preheader | (string $text, array $mail_args): string | Modify the preheader / inbox preview text |
cfeb_unsubscribe_url | (string $url, array $mail_args): string | Supply the unsubscribe URL for {#unsubscribe_url#} |
cfeb_site_address | (string $address): string | Supply the CAN-SPAM physical address for {#site_address#} |
cfeb_modify_email | (string $html, array $mail_args): string | Last-chance modification of the final rendered HTML before send |
cfeb_twig_context | (array $context, array $mail_args): array | Add or override variables in the Twig render context |
REST API
Base: wp-json/cfeb/v1 — all endpoints require manage_options capability.
Method | Endpoint | Description |
|---|---|---|
GET | /templates | List all templates |
POST | /templates | Create a template |
GET | /templates/{id} | Get a template |
POST | /templates/{id} | Update a template |
DELETE | /templates/{id} | Delete a template |
POST | /templates/{id}/duplicate | Duplicate a template |
GET | /templates/{id}/export | Export as portable JSON |
POST | /templates/import | Import from portable JSON |
GET | /templates/{id}/preview | Render with full pipeline (Twig + tokens) |
POST | /twig/preview | Render a Twig snippet for live preview in the editor |
GET | /settings | Get global settings |
POST | /settings | Update global settings |
POST | /test-email | Send a test email |
POST | /test-connection | Test the active mailer connection |
GET | /logs | Get log entries |
DELETE | /logs | Clear the log |
GET | /logs/export | Export log as CSV |
POST | /logs/{id}/resend | Resend a logged email |
