Try Live
Add Docs
Rankings
Pricing
Enterprise
Docs
Install
Theme
Install
Docs
Pricing
Enterprise
More...
More...
Try Live
Rankings
Create API Key
Add Docs
Email.md
https://github.com/unmta/emailmd
Admin
Email.md converts markdown into responsive, email-safe HTML that works across Gmail, Outlook, Apple
...
Tokens:
14,031
Snippets:
166
Trust Score:
5.6
Update:
1 month ago
Context
Skills
Chat
Benchmark
81.2
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# Email.md Email.md is a markdown-to-email library that converts markdown into responsive, email-safe HTML that renders perfectly across Gmail, Outlook, Apple Mail, Yahoo, and every other email client. Built on MJML under the hood, it eliminates the need to write complex HTML tables and inline styles while supporting standard markdown syntax plus extensions like buttons, directives, and theming. The library provides a simple `render()` function that accepts markdown with optional YAML frontmatter and returns complete HTML documents ready for sending. It includes built-in themes (light and dark), extensive customization options, and generates both HTML and plain text versions for proper MIME multipart emails. ## Installation Install Email.md via npm for use in your Node.js or browser projects. ```bash npm install emailmd ``` ## render(markdown, options?) The main function that converts markdown into email-safe HTML. Returns an object containing the HTML document, plain text version, and extracted frontmatter metadata. ```typescript import { render } from "emailmd"; // Basic usage const { html, text, meta } = render(` # Welcome to Acme! Thanks for signing up. We're excited to have you on board. [Get Started](https://example.com/start){button} `); // html → Complete email-safe HTML document (DOCTYPE, html, head, body) // text → Plain text version for text/plain MIME part // meta → Extracted frontmatter metadata // With theme customization const result = render(` # Sale Alert Everything is 50% off this weekend! [Shop Now](https://example.com/sale){button color="#dc2626"} `, { theme: { brandColor: '#e11d48', buttonColor: '#e11d48', fontFamily: 'Georgia, serif', } }); console.log(result.html); // Complete HTML email ready to send ``` ## RenderOptions Configuration options passed to the render function for theme customization and wrapper selection. ```typescript interface RenderOptions { theme?: Partial<Theme>; // Override default theme values wrapper?: 'default' | WrapperFn; // Custom email wrapper function } // Example with full options import { render, darkTheme } from "emailmd"; const { html } = render(markdown, { theme: { ...darkTheme, brandColor: '#e11d48', contentWidth: '640px', }, wrapper: 'default' }); ``` ## Theme The Theme interface defines all customizable visual properties for emails including colors, typography, and layout. ```typescript interface Theme { brandColor: string; // Links, highlights, accents (#18181b) headingColor: string; // Heading text (#09090b) bodyColor: string; // Body text (#71717a) backgroundColor: string; // Outer background (#fafafa) contentColor: string; // Content area background (#ffffff) cardColor: string; // Callout/code block background (#f4f4f5) buttonColor: string; // Primary button background (#18181b) buttonTextColor: string; // Button text (#fafafa) secondaryColor: string; // Secondary button border (#18181b) secondaryTextColor: string; // Secondary button text (#18181b) successColor: string; // Success button background (#16a34a) successTextColor: string; // Success button text (#ffffff) dangerColor: string; // Danger button background (#dc2626) dangerTextColor: string; // Danger button text (#ffffff) warningColor: string; // Warning button background (#d97706) warningTextColor: string; // Warning button text (#ffffff) fontFamily: string; // Font stack fontSize: string; // Base font size (16px) lineHeight: string; // Base line height (1.6) contentWidth: string; // Email width (600px) } // Using theme in render import { render, darkTheme, mergeTheme } from "emailmd"; // Use built-in dark theme const { html: darkHtml } = render(markdown, { theme: darkTheme }); // Override specific values on dark theme const { html: customDark } = render(markdown, { theme: { ...darkTheme, brandColor: "#e11d48" } }); // Custom theme with light base const { html: branded } = render(markdown, { theme: { brandColor: '#2563eb', buttonColor: '#2563eb', headingColor: '#1e3a8a', } }); ``` ## Frontmatter YAML frontmatter at the top of markdown files allows per-email theme overrides and metadata configuration using snake_case keys. ```markdown --- preheader: "Don't miss our biggest sale of the year" theme: dark brand_color: "#e11d48" button_color: "#059669" subject: "Summer Sale - 50% Off Everything" campaign_id: "summer-2024" --- # Summer Sale Everything is 50% off this weekend only! [Shop Now](https://example.com/sale){button} ::: footer **Acme Corp** · [Unsubscribe](https://example.com/unsub) ::: ``` ```typescript import { render } from "emailmd"; const markdown = ` --- preheader: "Your order has shipped" subject: "Order #12345 Shipped" tracking_number: "1Z999AA10123456784" --- # Your Order Has Shipped! Track your package using the button below. [Track Package](https://example.com/track){button} `; const { html, text, meta } = render(markdown); console.log(meta.preheader); // "Your order has shipped" console.log(meta.subject); // "Order #12345 Shipped" console.log(meta.tracking_number); // "1Z999AA10123456784" ``` ## Buttons Call-to-action buttons using the `{button}` attribute syntax with support for variants, colors, and side-by-side layouts. ```markdown <!-- Primary button --> [Get Started](https://example.com){button} <!-- Secondary (outline) button --> [Learn More](https://example.com){button.secondary} <!-- Semantic color variants --> [Confirm Account](https://example.com/confirm){button.success} [Delete Account](https://example.com/delete){button.danger} [Review Changes](https://example.com/review){button.warning} <!-- Custom color --> [Shop Sale](https://example.com/sale){button color="#dc2626"} <!-- Full-width button --> [Subscribe Now](https://example.com/subscribe){button width="full"} <!-- Side-by-side buttons (same line) --> [Accept](https://example.com/accept){button} [Decline](https://example.com/decline){button.secondary} <!-- Button with fallback URL for accessibility --> [Reset Password](https://example.com/reset){button fallback} <!-- Custom fallback text (for internationalization) --> [Réinitialiser](https://example.com/reset){button fallback="Si vous avez des difficultés, copiez cette URL :"} ``` ## Images Responsive, centered email images with attributes for width, alignment, and border radius. ```markdown <!-- Basic block image (centered by default) -->  <!-- With width control --> {width="400"} <!-- Alignment options --> {align="left"} <!-- Rounded corners (great for avatars) --> {width="80" border-radius="50%"} <!-- Linked/clickable image --> [](https://example.com/shop) <!-- Inline image with text --> Feature one with icon {width="20" height="20"} included. <!-- Float image with text wrapping --> {width="80" float="left"} **Monstera Deliciosa** Easy care · Bright indirect light · $42.00 ``` ## Tables Standard GitHub Flavored Markdown tables rendered as styled, email-safe HTML with automatic theme styling. ```markdown <!-- Basic table --> | Name | Role | Status | | ----- | ---------- | ------ | | Alice | Engineer | Active | | Bob | Designer | Active | | Carol | Manager | Away | <!-- Column alignment with colons --> | Item | Qty | Price | | :----------------------- | ----: | -------: | | Monstera Deliciosa, 6" | 1 | $42.00 | | Ceramic Pot, White | 1 | $18.00 | | **Total** | | **$60.00** | ``` ## Header Directive Content rendered above the main body area, typically used for logos or brand images. ```markdown <!-- Centered logo (default) --> ::: header {width="150"} ::: <!-- Left-aligned header --> ::: header left {width="150"} ::: <!-- Header with custom text color --> ::: header color=#1e40af **Acme Corp** ::: ``` ## Hero Directive Full-width section with a background image and overlaid content for impactful banner headers. ```markdown <!-- Basic hero with heading --> ::: hero https://example.com/hero.jpg # Welcome aboard Get started with your new account today. ::: <!-- Hero with button --> ::: hero https://example.com/sale-bg.jpg # Summer Sale Up to 50% off everything this weekend. [Shop Now](https://example.com/sale){button color="#e11d48"} ::: ``` ## Callout Directive Highlighted tip or note block with customizable alignment, padding, and colors. ```markdown <!-- Basic callout --> ::: callout **Pro tip:** You can customize your dashboard in Settings. ::: <!-- Centered callout --> ::: callout center **ABC-123** Your confirmation code. ::: <!-- Compact callout --> ::: callout compact Short note. ::: <!-- Custom colors --> ::: callout color=#1e40af bg=#eff6ff **Note:** Your account is pending review. ::: <!-- Combined parameters --> ::: callout center compact bg=#eff6ff **ABC-123** ::: ``` ## Highlight Directive Emphasized content block with brand color accent for promotions and key messages. ```markdown <!-- Basic highlight --> ::: highlight Limited time: first 100 signups get 50% off. ::: <!-- Centered highlight --> ::: highlight center **50% OFF** — This weekend only! ::: <!-- Compact with custom colors --> ::: highlight compact color=#ffffff bg=#dc2626 **URGENT:** Action required. ::: ``` ## Footer Directive Footer section with smaller, muted text for legal information and unsubscribe links. ```markdown <!-- Basic footer --> ::: footer **Acme Corp** · [Unsubscribe](https://example.com/unsub) · [Preferences](https://example.com/prefs) ::: <!-- Left-aligned footer --> ::: footer left © 2024 Acme Corp · All rights reserved. ::: <!-- Footer with custom text color --> ::: footer color=#9ca3af Legal text here. ::: ``` ## Centered Directive Center-aligned text block for sign-offs and short messages. ```markdown ::: centered Thanks for reading. The Acme Team ::: <!-- With custom color --> ::: centered color=#71717a Have questions? Reply to this email. ::: ``` ## Markdown Text Formatting Standard and extended markdown syntax for inline text formatting. ```markdown <!-- Basic formatting --> **Bold text** and *italic text* and ***bold italic***. ~~Strikethrough~~ for deleted content. `inline code` renders with a subtle background. <!-- Headings --> # Heading 1 ## Heading 2 ### Heading 3 <!-- Links --> [Visit our site](https://example.com) Autolinks work too: https://example.com <!-- Lists --> - First item - Second item - Third item 1. Step one 2. Step two 3. Step three <!-- Task lists --> - [x] Design approved - [x] Content written - [ ] Ready to send <!-- Blockquotes --> > "The best way to predict the future is to create it." > — Peter Drucker <!-- Highlighted text --> Don't miss our ==biggest sale of the year==! <!-- Subscript & Superscript --> H~2~O is water. E = mc^2^ is famous. <!-- Emoji shortcodes --> :wave: Welcome! :rocket: Let's go! :heart: ``` ## Custom Wrappers Replace the default email structure with a custom wrapper function for full control over MJML output. ```typescript import { render, buildHead, segmentsToMjml } from 'emailmd'; import type { WrapperFn, Segment, Theme } from 'emailmd'; // Custom wrapper with edge-to-edge background const edgeToEdgeWrapper: WrapperFn = (segments, theme, meta) => { const head = buildHead(theme, meta?.preheader as string); const body = segmentsToMjml(segments, theme); return ` <mjml> ${head} <mj-body background-color="${theme.brandColor}"> ${body} </mj-body> </mjml> `; }; const { html } = render(markdown, { wrapper: edgeToEdgeWrapper }); // Helper functions available: // buildHead(theme, preheader?) - Generates <mj-head> with styles and fonts // segmentsToMjml(segments, theme) - Converts parsed content to MJML body elements ``` ## Complete Email Examples Full email templates demonstrating common use cases with all features combined. ```typescript import { render, darkTheme } from "emailmd"; // Transactional email (order confirmation) const orderEmail = render(` --- preheader: "Your order has been confirmed" --- ::: header {width="120"} ::: # Order Confirmed Your order **#12345** has been placed and is being processed. | Item | Qty | Price | | :--------------------- | --: | ------: | | Wireless Headphones | 1 | $149.00 | | USB-C Cable | 2 | $24.00 | | **Total** | | **$173.00** | You'll receive a shipping confirmation once your order is on its way. [View Order](https://example.com/orders/12345){button} ::: footer **Acme Corp** · [Help](https://example.com/help) · [Unsubscribe](https://example.com/unsub) ::: `); // Newsletter with dark theme const newsletter = render(` --- preheader: "Weekly update from Acme" theme: dark brand_color: "#818cf8" --- ::: hero https://example.com/weekly-bg.jpg # This Week at Acme Your weekly product updates and tips ::: We've been busy shipping new features and squashing bugs. ::: highlight center **New Feature:** Dark mode is now available! ::: ::: callout **Pro tip:** Enable keyboard shortcuts in Settings for faster navigation. ::: [See What's New](https://example.com/changelog){button} [View Docs](https://example.com/docs){button.secondary} ::: footer **Acme Corp** · [Unsubscribe](https://example.com/unsub) ::: `); // Welcome email with custom branding const welcomeEmail = render(` --- preheader: "Welcome to Acme - Let's get started" subject: "Welcome to Acme!" --- # :wave: Welcome aboard! Thanks for signing up. We're thrilled to have you. Here's what you can do next: - [x] Create your account - [ ] Set up your profile - [ ] Invite your team [Complete Setup](https://example.com/setup){button.success fallback} ::: centered color=#71717a Questions? Just reply to this email. ::: ::: footer **Acme Corp** · San Francisco, CA · [Unsubscribe](https://example.com/unsub) ::: `, { theme: { brandColor: '#2563eb', buttonColor: '#2563eb', } }); // Access results console.log(orderEmail.html); // Complete HTML for text/html MIME part console.log(orderEmail.text); // Plain text for text/plain MIME part console.log(orderEmail.meta); // { preheader: "Your order has been confirmed" } ``` ## Summary Email.md is ideal for developers who need to send transactional emails (order confirmations, password resets, account notifications), marketing newsletters, and automated communications. The markdown-based approach makes templates readable and maintainable while the MJML foundation ensures bulletproof rendering across all email clients. Common integration patterns include using Email.md with email services like Resend, SendGrid, or AWS SES by passing the generated `html` and `text` to the service's send API. The library shines in scenarios where email templates need to be authored by non-developers or stored in databases/CMS systems, as plain markdown is far more accessible than HTML table layouts. For teams using AI to generate email content, Email.md's markdown syntax is naturally well-suited for LLM output. The theming system and frontmatter support enable brand consistency across all emails while allowing per-email customization when needed.