Build your first email: the ldnddev Monthly Newsletter
In this guide you turn the newsletter starter into a complete newsletter, top to bottom. It takes about 30 minutes. You'll use every main skill: editing blocks, adding blocks in the right place, working with columns, and arranging things.
Keys, screens, and commands may differ in other versions.
- Header with the ldnddev logo
- Hero: a dark background with a heading and a button
- Intro: a short paragraph and a button
- Divider
- Two columns, each with an image and a short blurb
- Divider
- Social links
- Footer: company details, unsubscribe link, and copyright
Image not captured yet. Finished ldnddev Monthly Newsletter at 600px, with each part labelled (header, hero, intro, divider, two columns, divider, social, footer)
Planned file: source/images/emailforge/build-your-first-email/build-your-first-email-01-finished-labelled.png
Alt text: The finished ldnddev Monthly Newsletter with its eight parts labelled from header to footer
When you're done, the Structure tree looks like this:
[HEAD] mj-head
[BRAND] brand
[BODY] mj-body (8)
├─ 1. email-header ← logo (kept from the starter)
├─ 2. mj-hero ← hero
│ ├─ mj-text (heading)
│ └─ mj-button
├─ 3. mj-section ← intro
│ └─ mj-column 100%
│ ├─ mj-text
│ └─ mj-button
├─ 4. mj-section ← divider
│ └─ mj-column 100%
│ └─ mj-divider
├─ 5. mj-section ← two columns
│ ├─ mj-column 50% (mj-image, mj-text)
│ └─ mj-column 50% (mj-image, mj-text)
├─ 6. mj-section ← divider
│ └─ mj-column 100%
│ └─ mj-divider
├─ 7. mj-section ← social links
│ └─ mj-column 100%
│ └─ mj-social
└─ 8. email-footer ← footer (kept from the starter)
Images and links used in this guide
| What | Use |
|---|---|
| Logo on a light background | https://res.cloudinary.com/eojrsoca/image/upload/v1790540409/logo-full-black-text.png |
| Logo on a dark background | https://res.cloudinary.com/eojrsoca/image/upload/v1790540410/logo-full-white-text.png |
| Hero background (placeholder) | https://dummyimage.com/600x300/0F1114/2A2D31.png&text=+ |
| Column 1 image (placeholder) | https://dummyimage.com/560x320/2A2D31/FFAF46.png&text=Project+spotlight |
| Column 2 image (placeholder) | https://dummyimage.com/560x320/2A2D31/64B4F5.png&text=Open+source |
| Links | https://www.ldnddev.com and pages on it (swap in your real pages) |
Gmail and Outlook don't show SVG images, so an SVG logo can disappear. Always use full https:// addresses for images in this guide.
You should have the template folder from Install and set up, with MJML installed and the app open:
dd_emailforge init ./ldnddev-monthly --from newsletter
cd ldnddev-monthly
npm install
dd_emailforge .
Keys you'll use most: j/k to move, l/h to expand/collapse, / to add a block, Enter to edit, Tab to move between fields, Ctrl+S to save the block, Esc to cancel. Press F1 any time you forget one.
Select the block you want the new one to follow, press /, type a few letters to filter the list, and press Enter.
- With a top-level block (such as the email-header or a section) selected, the new block goes right after it.
- With [BODY] selected, the new block goes at the very end, below the footer. You'd then have to move it up with
K, so it's easier to select the block it should follow. - With a column or a hero selected, content blocks (text, image, button, …) go inside it, at the end.
- With a content block selected, the new block goes right after it.
If a block lands in the wrong place, select it and press J or K to move it down or up.
d deletes right away, with no "are you sure?" step. Press u to undo (up to 20 steps) and U to redo. Changes save automatically about two seconds after you make them.
Select [BODY] and press l to expand it. The newsletter starter has six blocks:
- email-header: the logo bar
- email-hero: a heading, subheading, and optional image
- email-article ("Story one")
- email-article ("Story two")
- email-cta: a heading, text, and button ("See all")
- email-footer: company details and unsubscribe link
You'll keep and edit the email-header and the email-footer. The four blocks in between are quick to fill in, but they can't produce this design: the email-hero has no button or background image, and the two email-articles stack one above the other instead of sitting side by side. So you'll replace them with more flexible blocks.
- Select 2. email-hero and press
d. You'll see "Deleted." - Do the same for both email-article blocks and the email-cta.
- Stop when only email-header and email-footer are left. (Deleted the wrong one? Press
u.)
For a quicker, simpler newsletter you can edit them instead of deleting them. Select one and press Enter:
- email-hero: Image src, Image alt, Heading, Subheading, Background
- email-article: Image src, Image alt, Title, Copy, Link label, Link href, Image position (top, left, or right)
- email-cta: Heading, Copy, Button label, Button href, Background
Your result won't match the rest of this guide, but every check, preview, and export step works the same.
- Press
gto jump to the top and select [HEAD]. PressEnter. - Fill in:
- Name:
ldnddev Monthly Newsletter(the template's name) - Subject:
ldnddev Monthly Newsletter — October 2026 - Preheader:
Project spotlight, new terminal tools, and dd_emailforge 0.9.2.(the preview line many inboxes show after the subject) - Title:
ldnddev Monthly Newsletter
- Name:
- Leave Base URL empty. This guide uses full
https://image addresses, so you don't need it (see "Using local images" at the end). - Press
Ctrl+S.
Ctrl+U doesn't clear a field. Press End, then Backspace until it's empty (in a multi-line box, Ctrl+End first).
[BRAND] sets the fonts and colors for the whole email. Select [BRAND] and press Enter. It has six fields:
| Field | Value in this guide (starter default) |
|---|---|
| Font family | Arial, Helvetica, sans-serif |
| Text color | #1a1a1a |
| Background | #f4f4f4 |
| Content width | 600 |
| Button background | #FFAF46 |
| Button color | #0F1114 (the button's text color) |
This guide keeps the starter's values. Change any of them to match your brand, then press Ctrl+S (or Esc if you didn't change anything).
F2 opens the Theme, which only changes the colors of the dd_emailforge app on your screen. It has no effect on your email. Your email's look comes from [BRAND].
- Select 1. email-header and press
Enter. - Fill in:
- Logo src:
https://res.cloudinary.com/eojrsoca/image/upload/v1790540409/logo-full-black-text.png - Logo alt:
ldnddev, LLC - Logo href:
https://www.ldnddev.com - Logo width:
200px - Background:
#ffffff
- Logo src:
- Press
Ctrl+S.
If you set a dark Background, switch the logo to the white-text version: https://res.cloudinary.com/eojrsoca/image/upload/v1790540410/logo-full-white-text.png
A hero is a block with a background color or image. Text and buttons sit on top of it.
-
With 1. email-header selected, press
/and typehero. The list shows email-hero under "blocks" and mj-hero under "primitives". Choose mj-hero and pressEnter. It lands right after the header.
-
With the hero selected, press
Enterand fill in:- Mode:
fluid-height(use←/→to cycle the choices) - Background URL:
https://dummyimage.com/600x300/0F1114/2A2D31.png&text=+ - Background:
#0F1114(shows if the image doesn't load) - Background height:
300px - Background width:
600px - Background position:
center center - Padding:
48px 24px - Press
Ctrl+S.
- Mode:
-
With the hero still selected, press
/, typetext, and pressEnter. The text goes inside the hero. PressEnterto edit it:- Content:
ldnddev Monthly Newsletter - Align:
center - Font size:
32px - Font weight:
bold - Color:
#ffffff - Padding:
0 0 16px 0 - Press
Ctrl+S.
- Content:
-
With the heading text selected, press
/, typebutton, and pressEnter. The button goes right after the heading. Edit it:- Label:
Read this month's issue - Href:
https://www.ldnddev.com/blog/ - Align:
center - Press
Ctrl+S.
- Label:
The button picks up its colors from [BRAND] (Button background and Button color).
A hero only holds content blocks, so you can't add a section while the hero is selected. If you try, the picker shows "(nothing can be inserted here)".
Instead:
-
Select 1. email-header, press
/, typemj-section, and pressEnter. The section lands right after the header, above the hero. -
Press
Jonce to move it below the hero.
-
A new section is empty: it has no columns. With the section selected, press
Conce. That adds one column at 100% width, and the new column is selected. -
Press
/, typetext, and pressEnter. It goes into the column. PressEnterand edit it:- Content: your intro, for example:
Hi there, welcome to the October issue of the ldnddev Monthly Newsletter. This month we cover our latest Drupal and WordPress builds, a few terminal tools we can't stop using, and what's next for our open-source projects.(PressCtrl+Eto expand the Content box while you type.) - Font size:
16px - Press
Ctrl+S.
- Content: your intro, for example:
-
With the text selected, press
/, typebutton, and pressEnter. Edit it:- Label:
Visit our blog - Href:
https://www.ldnddev.com/blog/ - Align:
center - Press
Ctrl+S.
- Label:
If you give a button a Width in pixels, it must be wider than its left and right Inner padding added together. Otherwise validation (F3) reports an error. Leaving Width empty avoids this.
Each divider gets its own full-width section.
- Select the intro section (3. mj-section), press
/, typemj-section, and pressEnter. It lands right after the intro. - Press
Cto give it one column. - Press
/, typedivider, and pressEnter. PressEnterto edit it:- Border color:
#dddddd - Border width:
1px - Border style:
solid - Press
Ctrl+S.
- Border color:
-
Select the divider section (4. mj-section), press
/, typemj-section, and pressEnter. -
With the new section selected, press
Ctwice:- The first
Cadds one column at 100%. - The second
Cmakes two columns at 50% each.
After each
C, the newest column is selected, so you're now on the second column. - The first
Fill the first column:
- Press
cto select the previous (first) column. - Press
/, typeimage, and pressEnter. Edit it:- Src:
https://dummyimage.com/560x320/2A2D31/FFAF46.png&text=Project+spotlight - Alt:
Project spotlight placeholder image - Href:
https://www.ldnddev.com/results/(makes the image a link) - Press
Ctrl+S.
- Src:
- With the image selected, press
/, typetext, and pressEnter. Set Content to:<strong>Project spotlight</strong><br>A recent Drupal 11 build for a regional nonprofit, from discovery to launch in eight weeks.PressCtrl+S. (Content accepts simple HTML, such as<strong>for bold and<br>for a line break.)
Then the second column:
- Select the first column and press
vto jump to the next column. - Repeat steps 4 and 5 with:
- Src:
https://dummyimage.com/560x320/2A2D31/64B4F5.png&text=Open+source, Alt:Open-source tools placeholder image, Href:https://github.com/ldnddev - Content:
<strong>From the toolbox</strong><br>dd_emailforge 0.9.2 is out: build MJML email templates from your terminal.
- Src:
Want a button under each blurb? Select the text and add an mj-button the same way as in Step 6.
C adds a column and V removes one. Every C or V resets all the section's columns to equal widths, replacing any custom widths. For uneven columns (say 40% / 60%), finish adding or removing columns first, then select each column, press Enter, and set its Width.
You already built a divider section in Step 7, so copy it:
- Select the divider section (4. mj-section) and press
y. A copy appears right after it. - With the copy selected, press
Jonce to move it below the two-column section.
-
Select the second divider section (6. mj-section), press
/, typemj-section, and pressEnter. PressCto give it one column. -
Press
/, typesocial, and pressEnter. A new mj-social has no icons yet ("0 icons"). -
Press
Enterto edit it, then pressTabuntil you reach Icons. It reads "0 item(s) — A add · X remove · Enter edit".
-
Press
Ato add a row. New rows start as network x with the linkhttps://example.com. -
Press
Enteron the row. The Edit — social icon form opens:- Network: use
←/→to pick the network. For the first row, leave it onx. - Href:
https://x.com/jaredlyvers01 - Press
Ctrl+Sto go back to the Icons list.

- Network: use
-
Press
Aagain,Enter, set Network tolinkedin(press←once fromx) and Href tohttps://www.linkedin.com/in/jaredlyvers01/, thenCtrl+S. -
Press
Aagain,Enter, set Network togithub(press→once fromx) and Href tohttps://github.com/ldnddev, thenCtrl+S. -
Back on the mj-social form, press
Ctrl+Sto save it.
To remove a row, select it in the Icons list and press X.
The Network list has 16 choices: facebook, instagram, linkedin, x, github, youtube, pinterest, google, tumblr, snapchat, vimeo, medium, soundcloud, dribbble, xing, and web.
dd_emailforge v0.9.2 outputs the x network as MJML's twitter icon, so the email shows the blue Twitter bird, not the X logo. The link still goes to your X profile. To show the X logo, upload a PNG of it and put its https:// address in the row's Icon src (web) field.
- Press
gto go to the top, then step through the tree withj. Compare it with the tree at the top of this guide: eight blocks under [BODY]. - Move anything out of place with
J/K. Delete anything extra withd. - Made a mistake?
uundoes (up to 20 steps).UorCtrl+Rredoes. - Press
sto save now (this also writes atemplate.json.backupcopy).
-
Press
F3. If everything's fine, you'll see "✓ Validation passed". If not, a list of problems opens: pressEnteron one to jump straight to it, fix it, and pressF3again.
-
Press
pto open the preview in your browser. Check the email at desktop (600px) and phone (320px) widths. -
Press
Shift+Eto export. Your folder now hastemplate.html, ready to send.
These are covered in detail in Preview and validate and Export and send.
You can keep images in the template's images/ folder and pick them in FormEdit with Ctrl+P. Email apps can't see files on your computer, though, so before you export:
- Upload the images to a web host so they have public
https://addresses. - Select [HEAD], press
Enter, and set Base URL to thathttps://address.
dd_emailforge needs an https:// Base URL to export templates that use local images.
This is the complete template.json for the newsletter, exactly as built in dd_emailforge v0.9.2. It validates (dd_emailforge validate . exits 0).
{
"version": 1,
"name": "ldnddev Monthly Newsletter",
"subject": "ldnddev Monthly Newsletter — October 2026",
"preheader": "Project spotlight, new terminal tools, and dd_emailforge 0.9.2.",
"lang": "en",
"base_url": "",
"brand": {
"font_family": "Arial, Helvetica, sans-serif",
"text_color": "#1a1a1a",
"background_color": "#f4f4f4",
"content_width": 600,
"button_background": "#FFAF46",
"button_color": "#0F1114"
},
"head": {
"title": "ldnddev Monthly Newsletter",
"breakpoint": "480px",
"fonts": [],
"json_ld": "",
"css": "",
"css_inline": false
},
"body": {
"background_color": "",
"nodes": [
{
"type": "email-header",
"logo_src": "https://res.cloudinary.com/eojrsoca/image/upload/v1790540409/logo-full-black-text.png",
"logo_alt": "ldnddev, LLC",
"logo_href": "https://www.ldnddev.com",
"logo_width": "200px",
"background_color": "#ffffff"
},
{
"type": "mj-hero",
"mode": "fluid-height",
"background_url": "https://dummyimage.com/600x300/0F1114/2A2D31.png&text=+",
"background_color": "#0F1114",
"background_height": "300px",
"background_width": "600px",
"background_position": "center center",
"padding": "48px 24px",
"children": [
{
"type": "mj-text",
"content": "ldnddev Monthly Newsletter",
"align": "center",
"font_size": "32px",
"font_weight": "bold",
"color": "#ffffff",
"padding": "0 0 16px 0"
},
{
"type": "mj-button",
"content": "Read this month's issue",
"href": "https://www.ldnddev.com/blog/",
"align": "center"
}
]
},
{
"type": "mj-section",
"full_width": false,
"children": [
{
"type": "mj-column",
"width": "100%",
"components": [
{
"type": "mj-text",
"content": "Hi there, welcome to the October issue of the ldnddev Monthly Newsletter. This month we cover our latest Drupal and WordPress builds, a few terminal tools we can't stop using, and what's next for our open-source projects.",
"font_size": "16px"
},
{
"type": "mj-button",
"content": "Visit our blog",
"href": "https://www.ldnddev.com/blog/",
"align": "center"
}
]
}
]
},
{
"type": "mj-section",
"full_width": false,
"children": [
{
"type": "mj-column",
"width": "100%",
"components": [
{
"type": "mj-divider",
"border_color": "#dddddd",
"border_width": "1px",
"border_style": "solid"
}
]
}
]
},
{
"type": "mj-section",
"full_width": false,
"children": [
{
"type": "mj-column",
"width": "50%",
"components": [
{
"type": "mj-image",
"src": "https://dummyimage.com/560x320/2A2D31/FFAF46.png&text=Project+spotlight",
"alt": "Project spotlight placeholder image",
"href": "https://www.ldnddev.com/results/",
"fluid_on_mobile": true
},
{
"type": "mj-text",
"content": "<strong>Project spotlight</strong><br>A recent Drupal 11 build for a regional nonprofit, from discovery to launch in eight weeks."
}
]
},
{
"type": "mj-column",
"width": "50%",
"components": [
{
"type": "mj-image",
"src": "https://dummyimage.com/560x320/2A2D31/64B4F5.png&text=Open+source",
"alt": "Open-source tools placeholder image",
"href": "https://github.com/ldnddev",
"fluid_on_mobile": true
},
{
"type": "mj-text",
"content": "<strong>From the toolbox</strong><br>dd_emailforge 0.9.2 is out: build MJML email templates from your terminal."
}
]
}
]
},
{
"type": "mj-section",
"full_width": false,
"children": [
{
"type": "mj-column",
"width": "100%",
"components": [
{
"type": "mj-divider",
"border_color": "#dddddd",
"border_width": "1px",
"border_style": "solid"
}
]
}
]
},
{
"type": "mj-section",
"full_width": false,
"children": [
{
"type": "mj-column",
"width": "100%",
"components": [
{
"type": "mj-social",
"mode": "horizontal",
"align": "center",
"icon_size": "32px",
"elements": [
{
"name": "x",
"href": "https://x.com/jaredlyvers01"
},
{
"name": "linkedin",
"href": "https://www.linkedin.com/in/jaredlyvers01/"
},
{
"name": "github",
"href": "https://github.com/ldnddev"
}
]
}
]
}
]
},
{
"type": "email-footer",
"company_name": "ldnddev, LLC",
"address_lines": [
"ldnddev, LLC, Chelsea, AL 35043"
],
"unsubscribe_label": "Unsubscribe from this newsletter",
"unsubscribe_href": "*|UNSUB|*",
"social": [],
"copyright": "© 2026 ldnddev, LLC. All rights reserved."
}
]
}
}
Things to notice:
name,subject,preheader,lang, andbase_urlare top-level keys, even though you edit them on the [HEAD] row.headholdstitle,breakpoint,fonts,json_ld,css, andcss_inline.- Every node has a
"type"tag. Children live under different keys depending on the parent:children(mj-section, mj-hero),components(mj-column),elements(mj-social),social(email-footer). - The mj-button label is stored as
content. "name": "x"inelementsis emitted as MJMLtwitter.
Check and export the same folder without the app:
dd_emailforge validate . # prints nothing and exits 0 when valid
dd_emailforge export . --out dist # writes dist/template.mjml and dist/template.html
Commit the folder to git once it validates. See For developers.
The finished sample template folder, as built in dd_emailforge v0.9.2:
- template.json: the template you edit
- template.mjml: the generated MJML
- template.html: the exported HTML
- package.json: pins the
mjmlcompiler (runnpm install)
Put template.json and package.json in an empty folder, run npm install, then dd_emailforge .
Previous: A tour of the app · Next: Preview and validate