Envelopr is a live-reloading development tool for building MJML email templates with instant preview. Write your MJML templates and see changes in real-time, with support for Go template syntax for dynamic content.
- π Live preview with hot reload
- 𧩠Two-stage template processing (Go templates + MJML)
- π Support for partials and nested directory structures
- π± Responsive preview with mobile/tablet/desktop views
- π¨ Static template variables via YAML configuration
curl -sSfL https://raw.githubusercontent.com/esdete2/envelopr/master/install.sh | sh
With Go 1.23 or higher:
go install github.com/esdete2/envelopr@latest
- First enter into your project:
cd /path/to/your_project
- Create a default config file and directories:
envelopr init
- Create your first template in
documents/welcome.mjml
:
<mjml>
<mj-body>
<mj-section>
<mj-column>
<mj-text>Hello World!</mj-text>
</mj-column>
</mj-section>
</mj-body>
</mjml>
- Start the development server:
envelopr watch
- Open http://localhost:3600 in your browser
Envelopr uses a YAML configuration file (envelopr.yaml
):
paths:
documents: documents # MJML templates directory
partials: partials # Reusable components
output: output # Compiled HTML output
mjml:
validationLevel: soft # strict/soft/skip
keepComments: false # Preserve HTML comments
beautify: true # Pretty print HTML
minify: false # Minify output
fonts: # Custom web fonts
Roboto: https://fonts.googleapis.com/css?family=Roboto
template:
variables: # Global variables
companyName: ACME Corp
supportEmail: support@acme.com
documents: # Template-specific variables
welcome:
name: John Doe
activationLink: https://example.com/activate
Envelopr uses Go's template language with additional features for email template development.
Basic Go template syntax is supported with variables from your config file:
# With config:
template:
variables:
name: John
showHeader: true
items:
- name: Product
price: $99
# In template:
<!-- Variables -->
<mj-text>Hello {{ .name }}</mj-text>
<!-- Conditionals -->
{{ if .showHeader }}
{{ template "header" . }}
{{ end}}
<!-- Loops -->
{{ range .items}}
<mj-text>Item: {{ .name }} - {{ .price }}</mj-text>
{{ end}}
Template variables are defined in your envelopr.yaml
configuration.
Use expression
(or its shorter alias exp
) to preserve Go template expressions in the output HTML:
<mj-button href="{{ expression ".profileUrl" }}">
Visit Profile
</mj-button>
<!-- Same using shorter syntax -->
<mj-button href="{{ exp ".profileUrl" }}">
Visit Profile
</mj-button>
<!-- Output HTML (both variants) -->
<a href="{{ .profileUrl }}">Visit Profile</a>
Here's another example preserving loop and conditional expressions:
<mj-section>
<mj-column>
{{ exp "range .products" }}
<mj-text>{{ exp ".name" }}</mj-text>
{{ exp "if .onSale" }}
<mj-text color="red">Sale!</mj-text>
{{ exp "end" }}
{{ exp "end" }}
</mj-column>
</mj-section>
<!-- Output HTML -->
<div>
{{ range .products }}
<p>{{ .name }}</p>
{{ if .onSale }}
<p style="color: red">Sale!</p>
{{ end }}
{{ end }}
</div>
This is useful when the final HTML needs to be processed by go templates again.
Create reusable components in the partials
directory:
partials/layout.mjml
:
<mjml>
<mj-head>
<mj-title>{{ .title }}</mj-title>
</mj-head>
<mj-body>
{{ template "header" . }}
{{ template "content" . }} <!-- Main content injection -->
{{ template "footer" . }}
</mj-body>
</mjml>
partials/button.mjml
:
<mj-button
href="{{.url}}"
background-color="#2563eb"
border-radius="6px"
>
{{ .label }}
</mj-button>
Use them in your templates:
{{ template "layout" . }}
{{ define "content" }}
<mj-section>
<mj-column>
<mj-text>Welcome {{ .name }}!</mj-text>
{{ template "button" dict
"url" (exp ".campaignUrl")
"label" "Shop Now"
}}
</mj-column>
</mj-section>
{{ end }}
# Initialize new project
envelopr init
# Compile templates
envelopr build
# Start development server
envelopr watch
# Build with custom config file
envelopr build -c custom-config.yaml
# Watch with custom host and port
envelopr watch --host 127.0.0.1 --port 8080
# Initialize without interactive prompts
envelopr init -y
# Set log verbosity (1=error to 5=trace)
envelopr -v 4 watch
For a full list of commands and options, run envelopr --help
.
Pull requests are welcome! Feel free to:
- Report bugs
- Suggest new features
- Submit pull requests
Apache-2.0 license - see LICENSE for details.