Search

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.

What you'll build
  1. Header with the ldnddev logo
  2. Hero: a dark background with a heading and a button
  3. Intro: a short paragraph and a button
  4. Divider
  5. Two columns, each with an image and a short blurb
  6. Divider
  7. Social links
  8. Footer: company details, unsubscribe link, and copyright

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

WhatUse
Logo on a light backgroundhttps://res.cloudinary.com/eojrsoca/image/upload/v1790540409/logo-full-black-text.png
Logo on a dark backgroundhttps://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
Linkshttps://www.ldnddev.com and pages on it (swap in your real pages)
Before you start

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.

Step 1: Meet the starter

Select [BODY] and press l to expand it. The newsletter starter has six blocks:

  1. email-header: the logo bar
  2. email-hero: a heading, subheading, and optional image
  3. email-article ("Story one")
  4. email-article ("Story two")
  5. email-cta: a heading, text, and button ("See all")
  6. email-footer: company details and unsubscribe link
The Structure tree of the newsletter starter with six blocks: email-header, email-hero, two email-articles, email-cta and email-footer

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.

  1. Select 2. email-hero and press d. You'll see "Deleted."
  2. Do the same for both email-article blocks and the email-cta.
  3. Stop when only email-header and email-footer are left. (Deleted the wrong one? Press u.)
The Structure tree with only the email-header and email-footer left under BODY
Step 2: Set the email details in [HEAD]
  1. Press g to jump to the top and select [HEAD]. Press Enter.
  2. 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
  3. Leave Base URL empty. This guide uses full https:// image addresses, so you don't need it (see "Using local images" at the end).
  4. Press Ctrl+S.
The FormEdit window for HEAD with the newsletter name, subject and preheader filled in
Step 3: Check the brand in [BRAND]

[BRAND] sets the fonts and colors for the whole email. Select [BRAND] and press Enter. It has six fields:

FieldValue in this guide (starter default)
Font familyArial, Helvetica, sans-serif
Text color#1a1a1a
Background#f4f4f4
Content width600
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).

The FormEdit window for BRAND with font family, text color, background, content width and button colors
Step 5: Add the hero with a heading and a button

A hero is a block with a background color or image. Text and buttons sit on top of it.

  1. With 1. email-header selected, press / and type hero. The list shows email-hero under "blocks" and mj-hero under "primitives". Choose mj-hero and press Enter. It lands right after the header.

    The Insert picker filtered to hero, listing email-hero under blocks and mj-hero under primitives

  2. With the hero selected, press Enter and 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.
  3. With the hero still selected, press /, type text, and press Enter. The text goes inside the hero. Press Enter to edit it:

    • Content: ldnddev Monthly Newsletter
    • Align: center
    • Font size: 32px
    • Font weight: bold
    • Color: #ffffff
    • Padding: 0 0 16px 0
    • Press Ctrl+S.
  4. With the heading text selected, press /, type button, and press Enter. 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.
The Structure tree with a hero block containing a heading and a button

The button picks up its colors from [BRAND] (Button background and Button color).

Step 6: Add the intro text and button

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)".

The Insert picker showing nothing can be inserted here when a section is typed with the hero selected

Instead:

  1. Select 1. email-header, press /, type mj-section, and press Enter. The section lands right after the header, above the hero.

  2. Press J once to move it below the hero.

    A new empty section placed below the hero in the Structure tree

  3. A new section is empty: it has no columns. With the section selected, press C once. That adds one column at 100% width, and the new column is selected.

  4. Press /, type text, and press Enter. It goes into the column. Press Enter and 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. (Press Ctrl+E to expand the Content box while you type.)
    • Font size: 16px
    • Press Ctrl+S.
  5. With the text selected, press /, type button, and press Enter. Edit it:

    • Label: Visit our blog
    • Href: https://www.ldnddev.com/blog/
    • Align: center
    • Press Ctrl+S.
The Structure tree showing the intro section with a full-width column holding text and a button
Step 7: Add a divider

Each divider gets its own full-width section.

  1. Select the intro section (3. mj-section), press /, type mj-section, and press Enter. It lands right after the intro.
  2. Press C to give it one column.
  3. Press /, type divider, and press Enter. Press Enter to edit it:
    • Border color: #dddddd
    • Border width: 1px
    • Border style: solid
    • Press Ctrl+S.
The FormEdit window for a divider with border color dddddd, 1px width and solid style
Step 8: Add a two-column section
  1. Select the divider section (4. mj-section), press /, type mj-section, and press Enter.

  2. With the new section selected, press C twice:

    • The first C adds one column at 100%.
    • The second C makes two columns at 50% each.

    After each C, the newest column is selected, so you're now on the second column.

A section with two 50 percent columns shown in the Structure tree and the email outline

Fill the first column:

  1. Press c to select the previous (first) column.
  2. Press /, type image, and press Enter. 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.
  3. With the image selected, press /, type text, and press Enter. Set Content to: <strong>Project spotlight</strong><br>A recent Drupal 11 build for a regional nonprofit, from discovery to launch in eight weeks. Press Ctrl+S. (Content accepts simple HTML, such as <strong> for bold and <br> for a line break.)

Then the second column:

  1. Select the first column and press v to jump to the next column.
  2. 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.
The Structure tree showing two columns, each with an image and text

Want a button under each blurb? Select the text and add an mj-button the same way as in Step 6.

Step 9: Add the second divider

You already built a divider section in Step 7, so copy it:

  1. Select the divider section (4. mj-section) and press y. A copy appears right after it.
  2. With the copy selected, press J once to move it below the two-column section.
The Structure tree with a second divider section below the two-column section
Step 12: Tidy up
  1. Press g to go to the top, then step through the tree with j. Compare it with the tree at the top of this guide: eight blocks under [BODY].
  2. Move anything out of place with J/K. Delete anything extra with d.
  3. Made a mistake? u undoes (up to 20 steps). U or Ctrl+R redoes.
  4. Press s to save now (this also writes a template.json.backup copy).
The complete Structure tree of the ldnddev Monthly Newsletter with eight top-level blocks
Step 13: Check, preview, and export
  1. Press F3. If everything's fine, you'll see "✓ Validation passed". If not, a list of problems opens: press Enter on one to jump straight to it, fix it, and press F3 again.

    A Validation passed message in dd_emailforge

  2. Press p to open the preview in your browser. Check the email at desktop (600px) and phone (320px) widths.

  3. Press Shift+E to export. Your folder now has template.html, ready to send.

These are covered in detail in Preview and validate and Export and send.

Using local images

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:

  1. Upload the images to a web host so they have public https:// addresses.
  2. Select [HEAD], press Enter, and set Base URL to that https:// address.

dd_emailforge needs an https:// Base URL to export templates that use local images.

For developers: the finished template.json

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, and base_url are top-level keys, even though you edit them on the [HEAD] row. head holds title, breakpoint, fonts, json_ld, css, and css_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" in elements is emitted as MJML twitter.

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.