Free email template
Welcome email template
A short first email after sign-up: three next steps and one button. Free and MIT-licensed, in React Email, MJML, HTML and plain text, with light and dark mode built in.
- MIT license
- Works with any email provider
- Light and dark mode
What every welcome email needs.
The template covers the content. Points 1 and 4 are about how you send it.
Send it straight after sign-up
The best moment is while they still have your product open. A welcome that arrives the next day is just another email.
One main button
Take them back to the product. The template has one button, to the dashboard, and keeps every other link secondary.
Three next steps, not ten
A short list of the first useful things to do. Anything more is a manual, and nobody reads a manual in an email.
A reply address someone reads
The template says "reply to this email and a real person will get back to you". If you keep that line, set the reply-to address to an inbox your team watches, not noreply.
No sales pitch
Discount codes and upgrade offers turn a welcome into marketing, and it gets treated that way. Keep it about the account they just made.
Where to get help
A link to your help center, for the questions that come up on day one. The template puts it at the bottom.
The code. Copy the format your stack uses.
Change the brand name, logo and colors once in theme.ts and every template follows.
import * as React from 'react'
import { A, Button, Divider, Layout, P, Small, Title } from '../../components'
import type { TemplateMeta } from '../../components/meta'
import { plainText } from '../../components/text'
import { theme } from '../../theme'
export type WelcomeProps = {
name: string
dashboardUrl: string
helpUrl: string
}
export const meta: TemplateMeta = {
name: 'Welcome',
description: 'A short first email after sign-up: three next steps and one button.',
group: 'Account',
subject: `Welcome to ${theme.brand.name}`,
}
const steps: Array<[string, string]> = [
['Set up your workspace', 'Add your details so everything is ready when you need it.'],
['Invite your team', 'Work together from day one. Teammates join with one click.'],
['Get help any time', 'Reply to this email and a real person will get back to you.'],
]
export default function Welcome({ name, dashboardUrl, helpUrl }: WelcomeProps) {
return (
<Layout
preview="Your account is ready. Here are three good places to start."
footerNote="You're receiving this because you just created an account."
>
<Title>Welcome, {name}</Title>
<P>Thanks for signing up. Your account is ready. Here are three good places to start:</P>
{steps.map(([title, body], index) => (
<P key={title} style={{ margin: '0 0 12px' }}>
<strong>
{index + 1}. {title}
</strong>
<br />
<span className="em-muted" style={{ color: theme.colors.light.muted }}>
{body}
</span>
</P>
))}
<Button href={dashboardUrl}>Go to your dashboard</Button>
<Divider />
<Small style={{ margin: 0 }}>
Questions? Reply to this email or visit the <A href={helpUrl}>help center</A>.
</Small>
</Layout>
)
}
Welcome.PreviewProps = {
name: 'Ada',
dashboardUrl: 'https://example.com/dashboard',
helpUrl: 'https://example.com/help',
} satisfies WelcomeProps
export function text({ name, dashboardUrl, helpUrl }: WelcomeProps) {
return plainText(
`Welcome, ${name}`,
'Thanks for signing up. Your account is ready. Here are three good places to start:',
steps.map(([title, body], index) => `${index + 1}. ${title}\n ${body}`).join('\n\n'),
`Go to your dashboard: ${dashboardUrl}`,
`Questions? Reply to this email or visit the help center: ${helpUrl}`,
)
}
<mjml lang="en" dir="ltr">
<mj-head>
<mj-title>Welcome</mj-title>
<mj-preview>Your account is ready. Here are three good places to start.</mj-preview>
<!-- theme:start -->
<!-- Generated from theme.ts by `npm run build`. Edit theme.ts, not this block. -->
<mj-raw>
<meta name="color-scheme" content="light dark" />
<meta name="supported-color-schemes" content="light dark" />
</mj-raw>
<mj-attributes>
<mj-all font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif" />
<mj-body background-color="#f4f4f5" width="560px" />
<mj-wrapper padding="40px 16px" />
<mj-section padding="0" />
<mj-column padding="0" />
<mj-text padding="0 0 16px" font-size="15px" line-height="24px" color="#18181b" css-class="em-text" />
<mj-button align="left" background-color="#2f5bd3" color="#ffffff" font-size="15px" font-weight="600" line-height="20px" border-radius="8px" inner-padding="12px 22px" padding="8px 0 24px" css-class="em-button" />
<mj-divider border-width="1px" border-color="#e4e4e7" padding="12px 0 28px" css-class="em-rule" />
<mj-table padding="0 0 24px" font-size="14px" line-height="20px" color="#18181b" />
<mj-class name="card" background-color="#ffffff" border="1px solid #e4e4e7" border-radius="12px" padding="40px" css-class="em-card" />
<mj-class name="h1" font-size="24px" line-height="32px" font-weight="650" letter-spacing="-0.3px" css-class="em-text em-h1" />
<mj-class name="small" font-size="13px" line-height="20px" color="#52525b" padding="0 0 12px" css-class="em-muted" />
<mj-class name="danger" background-color="#b42318" css-class="em-button-danger" />
<mj-class name="footer" font-size="12px" line-height="18px" color="#52525b" align="center" padding="0 0 6px" css-class="em-muted" />
</mj-attributes>
<mj-style inline="inline">
.em-label { padding: 10px 0; color: #52525b; width: 45%; vertical-align: top; }
.em-value { padding: 10px 0; color: #18181b; text-align: right; vertical-align: top; }
.em-row-border { border-top: 1px solid #e4e4e7; }
.em-total { padding: 12px 0 10px; color: #18181b; font-weight: 650; border-top: 2px solid #18181b; vertical-align: top; }
.em-total-value { padding: 12px 0 10px; color: #18181b; font-weight: 650; border-top: 2px solid #18181b; text-align: right; vertical-align: top; }
.em-codebox { margin: 8px 0 8px; padding: 18px 12px; background-color: #f4f4f5; border: 1px solid #e4e4e7; border-radius: 8px; text-align: center; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace; font-size: 32px; line-height: 40px; font-weight: 700; letter-spacing: 8px; color: #18181b; }
.em-callout { padding: 14px 16px; background-color: #f4f4f5; border: 1px solid #e4e4e7; border-radius: 8px; font-size: 14px; line-height: 22px; color: #18181b; }
.em-track { height: 8px; font-size: 1px; line-height: 8px; border-radius: 999px; background-color: #f4f4f5; }
.em-fill { height: 8px; font-size: 1px; line-height: 8px; border-radius: 999px; background-color: #2f5bd3; }
.em-link { color: #2f5bd3; text-decoration: underline; }
.em-step { color: #52525b; }
</mj-style>
<mj-style>
body { -webkit-font-smoothing: antialiased; }
:root { color-scheme: light dark; supported-color-schemes: light dark; }
.em-logo-dark { display: none; }
@media (prefers-color-scheme: dark) {
body, .em-page { background-color: #0e0e10 !important; }
.em-card, .em-card > table, .em-card > table > tbody > tr > td { background-color: #18181b !important; border-color: #2e2e33 !important; }
.em-text, .em-text > div { color: #f4f4f5 !important; }
.em-muted, .em-muted > div, .em-muted a { color: #a1a1aa !important; }
.em-link, .em-text a { color: #7a9bff !important; }
.em-wordmark, .em-wordmark > div, .em-wordmark a { color: #f4f4f5 !important; }
.em-subtle { background-color: #232327 !important; border-color: #2e2e33 !important; }
.em-border { border-color: #2e2e33 !important; }
.em-strong-border { border-color: #f4f4f5 !important; }
.em-rule, .em-rule p { border-top-color: #2e2e33 !important; }
.em-track { background-color: #232327 !important; }
.em-fill { background-color: #7a9bff !important; }
a.em-button, .em-button a, .em-button td[bgcolor] { background-color: #7a9bff !important; color: #0b0d14 !important; border-color: #7a9bff !important; }
a.em-button-danger, .em-button-danger a, .em-button-danger td[bgcolor] { background-color: #f97066 !important; color: #0b0d14 !important; border-color: #f97066 !important; }
.em-logo-light { display: none !important; }
.em-logo-dark { display: block !important; }
}
[data-ogsc] .em-card, [data-ogsc] .em-card > table, [data-ogsc] .em-card > table > tbody > tr > td { border-color: #2e2e33 !important; }
[data-ogsc] .em-text, [data-ogsc] .em-text > div { color: #f4f4f5 !important; }
[data-ogsc] .em-muted, [data-ogsc] .em-muted > div, [data-ogsc] .em-muted a { color: #a1a1aa !important; }
[data-ogsc] .em-link, [data-ogsc] .em-text a { color: #7a9bff !important; }
[data-ogsc] .em-wordmark, [data-ogsc] .em-wordmark > div, [data-ogsc] .em-wordmark a { color: #f4f4f5 !important; }
[data-ogsc] .em-subtle { border-color: #2e2e33 !important; }
[data-ogsc] .em-border { border-color: #2e2e33 !important; }
[data-ogsc] .em-strong-border { border-color: #f4f4f5 !important; }
[data-ogsc] .em-rule, [data-ogsc] .em-rule p { border-top-color: #2e2e33 !important; }
[data-ogsc] a.em-button, [data-ogsc] .em-button a, [data-ogsc] .em-button td[bgcolor] { color: #0b0d14 !important; border-color: #7a9bff !important; }
[data-ogsc] a.em-button-danger, [data-ogsc] .em-button-danger a, [data-ogsc] .em-button-danger td[bgcolor] { color: #0b0d14 !important; border-color: #f97066 !important; }
[data-ogsb] body, [data-ogsb] .em-page { background-color: #0e0e10 !important; }
[data-ogsb] .em-card, [data-ogsb] .em-card > table, [data-ogsb] .em-card > table > tbody > tr > td { background-color: #18181b !important; border-color: #2e2e33 !important; }
[data-ogsb] .em-subtle { background-color: #232327 !important; border-color: #2e2e33 !important; }
[data-ogsb] .em-border { border-color: #2e2e33 !important; }
[data-ogsb] .em-strong-border { border-color: #f4f4f5 !important; }
[data-ogsb] .em-rule, [data-ogsb] .em-rule p { border-top-color: #2e2e33 !important; }
[data-ogsb] .em-track { background-color: #232327 !important; }
[data-ogsb] .em-fill { background-color: #7a9bff !important; }
[data-ogsb] a.em-button, [data-ogsb] .em-button a, [data-ogsb] .em-button td[bgcolor] { background-color: #7a9bff !important; border-color: #7a9bff !important; }
[data-ogsb] a.em-button-danger, [data-ogsb] .em-button-danger a, [data-ogsb] .em-button-danger td[bgcolor] { background-color: #f97066 !important; border-color: #f97066 !important; }
@media only screen and (max-width: 600px) {
.em-card > table > tbody > tr > td { padding: 32px 24px !important; }
.em-h1, .em-h1 > div { font-size: 22px !important; line-height: 30px !important; }
}
</mj-style>
<!-- theme:end -->
</mj-head>
<mj-body>
<!-- header:start -->
<!-- Generated from theme.ts by `npm run build`. Edit theme.ts, not this block. -->
<mj-wrapper css-class="em-page">
<mj-section padding="0 8px 24px">
<mj-column>
<mj-text padding="0" font-size="18px" line-height="28px" font-weight="700" letter-spacing="-0.2px" css-class="em-wordmark"><a href="https://example.com" style="color:#18181b;text-decoration:none;">Acme</a></mj-text>
</mj-column>
</mj-section>
<!-- header:end -->
<mj-section mj-class="card">
<mj-column>
<mj-text mj-class="h1">Welcome, {{name}}</mj-text>
<mj-text>Thanks for signing up. Your account is ready. Here are three good places to start:</mj-text>
<mj-text padding="0 0 12px"><strong>1. Set up your workspace</strong><br /><span class="em-step em-muted">Add your details so everything is ready when you need it.</span></mj-text>
<mj-text padding="0 0 12px"><strong>2. Invite your team</strong><br /><span class="em-step em-muted">Work together from day one. Teammates join with one click.</span></mj-text>
<mj-text padding="0 0 12px"><strong>3. Get help any time</strong><br /><span class="em-step em-muted">Reply to this email and a real person will get back to you.</span></mj-text>
<mj-button href="{{dashboard_url}}">Go to your dashboard</mj-button>
<mj-divider />
<mj-text mj-class="small" padding="0">Questions? Reply to this email or visit the <a class="em-link" href="{{help_url}}">help center</a>.</mj-text>
</mj-column>
</mj-section>
<mj-section padding="24px 8px 0">
<mj-column>
<mj-text mj-class="footer">You're receiving this because you just created an account.</mj-text>
</mj-column>
</mj-section>
<!-- footer:start -->
<!-- Generated from theme.ts by `npm run build`. Edit theme.ts, not this block. -->
<mj-section padding="0 8px">
<mj-column>
<mj-text mj-class="footer">Acme Inc. · 100 Market Street · San Francisco, CA 94105</mj-text>
</mj-column>
</mj-section>
</mj-wrapper>
<!-- footer:end -->
</mj-body>
</mjml>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html dir="ltr" lang="en">
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<meta name="x-apple-disable-message-reformatting" />
<meta name="color-scheme" content="light dark" />
<meta name="supported-color-schemes" content="light dark" />
<title>Your account is ready. Here are three good places to start.</title>
<style>
:root { color-scheme: light dark; supported-color-schemes: light dark; }
.em-logo-dark { display: none; }
@media (prefers-color-scheme: dark) {
.em-page, .em-page > table > tbody > tr > td { background-color: #0e0e10 !important; }
.em-card { background-color: #18181b !important; border-color: #2e2e33 !important; }
.em-text, .em-text > div { color: #f4f4f5 !important; }
.em-muted, .em-muted > div, .em-muted a { color: #a1a1aa !important; }
.em-link, .em-text a { color: #7a9bff !important; }
.em-wordmark, .em-wordmark > div, .em-wordmark a { color: #f4f4f5 !important; }
.em-subtle { background-color: #232327 !important; border-color: #2e2e33 !important; }
.em-border { border-color: #2e2e33 !important; }
.em-strong-border { border-color: #f4f4f5 !important; }
.em-rule, .em-rule p { border-top-color: #2e2e33 !important; }
.em-track { background-color: #232327 !important; }
.em-fill { background-color: #7a9bff !important; }
a.em-button, .em-button a, .em-button td[bgcolor] { background-color: #7a9bff !important; color: #0b0d14 !important; border-color: #7a9bff !important; }
a.em-button-danger, .em-button-danger a, .em-button-danger td[bgcolor] { background-color: #f97066 !important; color: #0b0d14 !important; border-color: #f97066 !important; }
.em-logo-light { display: none !important; }
.em-logo-dark { display: block !important; }
}
[data-ogsc] .em-card { border-color: #2e2e33 !important; }
[data-ogsc] .em-text, [data-ogsc] .em-text > div { color: #f4f4f5 !important; }
[data-ogsc] .em-muted, [data-ogsc] .em-muted > div, [data-ogsc] .em-muted a { color: #a1a1aa !important; }
[data-ogsc] .em-link, [data-ogsc] .em-text a { color: #7a9bff !important; }
[data-ogsc] .em-wordmark, [data-ogsc] .em-wordmark > div, [data-ogsc] .em-wordmark a { color: #f4f4f5 !important; }
[data-ogsc] .em-subtle { border-color: #2e2e33 !important; }
[data-ogsc] .em-border { border-color: #2e2e33 !important; }
[data-ogsc] .em-strong-border { border-color: #f4f4f5 !important; }
[data-ogsc] .em-rule, [data-ogsc] .em-rule p { border-top-color: #2e2e33 !important; }
[data-ogsc] a.em-button, [data-ogsc] .em-button a, [data-ogsc] .em-button td[bgcolor] { color: #0b0d14 !important; border-color: #7a9bff !important; }
[data-ogsc] a.em-button-danger, [data-ogsc] .em-button-danger a, [data-ogsc] .em-button-danger td[bgcolor] { color: #0b0d14 !important; border-color: #f97066 !important; }
[data-ogsb] .em-page, [data-ogsb] .em-page > table > tbody > tr > td { background-color: #0e0e10 !important; }
[data-ogsb] .em-card { background-color: #18181b !important; border-color: #2e2e33 !important; }
[data-ogsb] .em-subtle { background-color: #232327 !important; border-color: #2e2e33 !important; }
[data-ogsb] .em-border { border-color: #2e2e33 !important; }
[data-ogsb] .em-strong-border { border-color: #f4f4f5 !important; }
[data-ogsb] .em-rule, [data-ogsb] .em-rule p { border-top-color: #2e2e33 !important; }
[data-ogsb] .em-track { background-color: #232327 !important; }
[data-ogsb] .em-fill { background-color: #7a9bff !important; }
[data-ogsb] a.em-button, [data-ogsb] .em-button a, [data-ogsb] .em-button td[bgcolor] { background-color: #7a9bff !important; border-color: #7a9bff !important; }
[data-ogsb] a.em-button-danger, [data-ogsb] .em-button-danger a, [data-ogsb] .em-button-danger td[bgcolor] { background-color: #f97066 !important; border-color: #f97066 !important; }
@media only screen and (max-width: 600px) {
.em-card-body > tbody > tr > td { padding: 32px 24px !important; }
.em-h1, .em-h1 > div { font-size: 22px !important; line-height: 30px !important; }
}
</style>
</head>
<body
class="em-page"
dir="ltr"
lang="en"
style="background-color:#f4f4f5;margin:0;padding:0">
<div
style="display:none;overflow:hidden;line-height:1px;opacity:0;max-height:0;max-width:0"
data-skip-in-text="true">
Your account is ready. Here are three good places to start.
<div>
</div>
</div>
<table
border="0"
width="100%"
cellpadding="0"
cellspacing="0"
role="presentation"
align="center">
<tbody>
<tr>
<td
dir="ltr"
lang="en"
style="margin:0;padding:0;background-color:#f4f4f5;font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;-webkit-font-smoothing:antialiased">
<table
align="center"
width="100%"
class="em-page"
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="max-width:560px;width:100%;margin:0 auto">
<tbody>
<tr style="width:100%">
<td style="padding:40px 16px">
<table
align="center"
width="100%"
border="0"
cellpadding="0"
cellspacing="0"
role="presentation">
<tbody>
<tr>
<td style="padding:0 8px 24px">
<a
href="https://example.com"
style="color:#067df7;text-decoration-line:none;text-decoration:none"
target="_blank"
><p
class="em-wordmark"
style="font-size:18px;line-height:28px;margin:0;font-weight:700;letter-spacing:-0.2px;color:#18181b;margin-top:0;margin-bottom:0;margin-left:0;margin-right:0">
Acme
</p></a
>
</td>
</tr>
</tbody>
</table>
<table
align="center"
width="100%"
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
class="em-card"
style="background-color:#ffffff;border:1px solid #e4e4e7;border-radius:12px">
<tbody>
<tr>
<td>
<table
align="center"
width="100%"
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
class="em-card-body">
<tbody>
<tr>
<td style="padding:40px 40px">
<h1
class="em-text em-h1"
style="margin:0 0 16px;font-size:24px;line-height:32px;font-weight:650;letter-spacing:-0.3px;color:#18181b">
Welcome, {{name}}
</h1>
<p
class="em-text"
style="font-size:15px;line-height:24px;margin:0 0 16px;color:#18181b;margin-top:0;margin-right:0;margin-bottom:16px;margin-left:0">
Thanks for signing up. Your account is
ready. Here are three good places to
start:
</p>
<p
class="em-text"
style="font-size:15px;line-height:24px;margin:0 0 12px;color:#18181b;margin-top:0;margin-right:0;margin-bottom:12px;margin-left:0">
<strong>1. Set up your workspace</strong
><br /><span
class="em-muted"
style="color:#52525b"
>Add your details so everything is ready
when you need it.</span
>
</p>
<p
class="em-text"
style="font-size:15px;line-height:24px;margin:0 0 12px;color:#18181b;margin-top:0;margin-right:0;margin-bottom:12px;margin-left:0">
<strong>2. Invite your team</strong
><br /><span
class="em-muted"
style="color:#52525b"
>Work together from day one. Teammates
join with one click.</span
>
</p>
<p
class="em-text"
style="font-size:15px;line-height:24px;margin:0 0 12px;color:#18181b;margin-top:0;margin-right:0;margin-bottom:12px;margin-left:0">
<strong>3. Get help any time</strong
><br /><span
class="em-muted"
style="color:#52525b"
>Reply to this email and a real person
will get back to you.</span
>
</p>
<table
align="center"
width="100%"
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="margin:8px 0 24px">
<tbody>
<tr>
<td>
<a
class="em-button"
href="{{dashboard_url}}"
style="line-height:20px;text-decoration:none;display:inline-block;max-width:100%;mso-padding-alt:0px;background-color:#2f5bd3;color:#ffffff;font-size:15px;font-weight:600;border-radius:8px;padding:12px 22px;padding-top:12px;padding-right:22px;padding-bottom:12px;padding-left:22px"
target="_blank"
><span
><!--[if mso]><i style="mso-font-width:366.66666666666663%;mso-text-raise:18px" hidden>   </i><![endif]--></span
><span
style="max-width:100%;display:inline-block;line-height:120%;mso-padding-alt:0px;mso-text-raise:9px"
>Go to your dashboard</span
><span
><!--[if mso]><i style="mso-font-width:366.66666666666663%" hidden>   ​</i><![endif]--></span
></a
>
</td>
</tr>
</tbody>
</table>
<hr
class="em-rule"
style="width:100%;border:none;border-color:transparent;border-top:1px solid #e4e4e7;margin:28px 0" />
<p
class="em-muted"
style="font-size:13px;line-height:20px;margin:0;color:#52525b;margin-top:0;margin-bottom:0;margin-left:0;margin-right:0">
Questions? Reply to this email or visit
the
<a
class="em-link"
href="{{help_url}}"
style="color:#2f5bd3;text-decoration-line:none;text-decoration:underline"
target="_blank"
>help center</a
>.
</p>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<table
align="center"
width="100%"
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="text-align:center">
<tbody>
<tr>
<td style="padding:24px 8px 0">
<p
class="em-muted"
style="font-size:12px;line-height:18px;margin:0 0 6px;color:#52525b;margin-top:0;margin-right:0;margin-bottom:6px;margin-left:0">
You're receiving this because you just
created an account.
</p>
<p
class="em-muted"
style="font-size:12px;line-height:18px;margin:0 0 6px;color:#52525b;margin-top:0;margin-right:0;margin-bottom:6px;margin-left:0">
Acme Inc. · 100 Market Street · San Francisco, CA
94105
</p>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</body>
</html>
Welcome, {{name}}
Thanks for signing up. Your account is ready. Here are three good places to start:
1. Set up your workspace
Add your details so everything is ready when you need it.
2. Invite your team
Work together from day one. Teammates join with one click.
3. Get help any time
Reply to this email and a real person will get back to you.
Go to your dashboard: {{dashboard_url}}
Questions? Reply to this email or visit the help center: {{help_url}}
--
Acme
Acme Inc. · 100 Market Street · San Francisco, CA 94105
# Create the template in your account once
npx -y --package=groundmail-cli -- groundmail templates push templates/welcome/welcome.html \
--alias welcome \
--name "Welcome" \
--subject "Welcome to Acme" \
--text templates/welcome/welcome.txt \
--publish
// Then send it by alias from your app
import { Groundmail } from 'groundmail'
const groundmail = new Groundmail(process.env.GROUNDMAIL_API_KEY!)
await groundmail.emails.send({
from: 'Acme <noreply@yourdomain.com>',
to: 'ada@example.com',
template: {
id: 'welcome',
variables: {
name: 'Ada',
dashboard_url: 'https://example.com/dashboard',
help_url: 'https://example.com/help',
},
},
})welcome.tsx, 68 lines, shown in full (scroll inside the panel). Typed props. Copy it with theme.ts and components/ from the repo. View on GitHub
Send it with Groundmail
Create the template in your account once, then send it by alias from your app.
npx -y --package=groundmail-cli -- groundmail templates push templates/welcome/welcome.html \
--alias welcome \
--name "Welcome" \
--subject "Welcome to Acme" \
--text templates/welcome/welcome.txt \
--publishimport { Groundmail } from 'groundmail'
const groundmail = new Groundmail(process.env.GROUNDMAIL_API_KEY!)
await groundmail.emails.send({
from: 'Acme <noreply@yourdomain.com>',
to: 'ada@example.com',
template: {
id: 'welcome',
variables: {
name: 'Ada',
dashboard_url: 'https://example.com/dashboard',
help_url: 'https://example.com/help',
},
},
})The CLI command and the Node.js send from the template's README, which also has Python, PHP and cURL. View on GitHub
Subject lines
This is the one email people expect from you, so the subject can be warm. It still needs the product name.
- Welcome to AcmeDefaultShort, expected and unmistakable.
- Welcome to Acme, {{name}}GoodAdds their name, which you already have from sign-up.
- Your Acme account is readyGoodSays what happened, for products where people sign up to do a job.
- You won't believe what Acme can do for you!AvoidHype and an exclamation mark read as marketing, and it doesn't say the account is ready.
The first email is the one people decide to trust
If the welcome lands in spam, people may never look for the emails after it. It also sets the pattern: from name, domain and tone should match everything else you send.
Google, Yahoo and Microsoft sender rules →- Send from your own domain with SPF, DKIM and DMARC set up.
- Send it from the same from name and domain as your other account emails.
- If you add offers or newsletters to it, it's marketing: send it on that stream instead.
- Groundmail sends this template by alias from your own domain, on our own mail servers. Send it with Groundmail
More account templates
All email templates →- Team invite email templateInvites someone to a team or workspace, naming who sent it and the role they get.
- New sign-in alert email templateA security alert for a sign-in from a new device, with details and a "secure my account" path.
- Account deletion email templateConfirms a deletion request and offers a grace period to restore the account.
Questions
Is it free to use?
Yes. The templates are MIT-licensed: use them in commercial products and change them however you like.
Do I need Groundmail to use it?
No. The HTML and text files use plain placeholders that work with most providers' template engines and with Handlebars or Mustache. Sending through Groundmail just saves a step.
Does it work in dark mode and Outlook?
Yes. The full HTML file carries dark-mode styles for Apple Mail and Outlook.com, and the extra markup desktop Outlook needs to draw the button.
How do I change the colors and logo?
Edit theme.ts once (name, logo, address and colors for light and dark) and rebuild. Every template in the set picks it up.