How Rendering Works
Templatical separates template editing from template rendering. The editor produces JSON; the renderer turns that JSON into MJML. You then compile the MJML to HTML using any MJML library and send it via your email service.
The pipeline
JSON -- The editor's native format. A
TemplateContentobject with ablocksarray andsettingsobject. Save this to let users resume editing later.MJML -- An intermediate markup language designed for email. Each Templatical block maps to an MJML component (
<mj-text>,<mj-image>,<mj-button>, etc.). MJML handles the hard parts of email HTML: responsive tables, Outlook conditionals, and cross-client compatibility. This is what Templatical's renderer produces.HTML -- The final output. MJML compiles to a complete HTML document with inline styles, nested tables, and client-specific workarounds. You compile this step yourself using any MJML library:
Language Library Node.js mjml (official) PHP spatie/mjml-php Python mrml-python Ruby mrml-ruby Rust mrml .NET Mjml.Net Elixir mjml_nif See the full list on mjml.io/community.
Why MJML?
MJML is an open-source markup language designed specifically for email. Email HTML is notoriously difficult. Every email client renders HTML differently -- Outlook uses Microsoft Word's rendering engine, Gmail strips <style> tags, Apple Mail supports modern CSS but Yahoo doesn't. Writing HTML that works everywhere requires:
- Nested tables for layout (flexbox and grid don't work)
- Inline styles on every element (external/embedded stylesheets are stripped)
- Outlook-specific conditional comments (
<!--[if mso]>) - Responsive breakpoints via
<style>tags for clients that support them
MJML abstracts all of this. You write semantic components (<mj-section>, <mj-column>, <mj-text>), and MJML compiles them to compatible HTML.
By producing MJML instead of HTML directly, Templatical stays lightweight and gives you full control over the final output. You can use any MJML compiler in any language, and you can modify the MJML before compiling — injecting custom components, adding tracking pixels, or transforming the markup to fit your sending platform's requirements.
What to store
Save both JSON and MJML to your database when the user saves. JSON lets users re-open and edit the template. MJML is what you compile to HTML at send time. The Quick Start example shows this pattern.
What the renderer does
@templatical/renderer takes a TemplateContent JSON object and produces a complete MJML document. Specifically, it:
- Converts each block in the JSON tree to its corresponding MJML component (text →
<mj-text>, image →<mj-image>, button →<mj-button>, etc.) - Applies block styles (padding, margin, background color) as MJML attributes
- Handles responsive overrides for tablet and mobile viewports
- Injects custom font declarations as
<mj-font>tags - Preserves merge tags unchanged (they pass through as literal text)
- Respects
visibilitysettings -- blocks hidden on all viewports are omitted - Wraps blocks with
displayConditionbefore/after strings - Optionally strips raw HTML blocks when
allowHtmlBlocksisfalse
What the renderer does NOT do
- Compile MJML to HTML -- Use any MJML library for this step.
- Evaluate merge tags -- Tags like
{{ first_name }}pass through as-is and are replaced at send time by your email platform. - Evaluate display conditions -- Conditional wrapping (e.g.,
{% if %}) passes through for your sending platform to process. - Send emails -- The renderer produces MJML. Sending is handled by your email service.
- Optimize images -- Images are referenced by URL. The renderer doesn't download, resize, or optimize them.
Next steps
- Renderer API -- full
renderToMjml()reference