拖拽
用户通过按自己想要的顺序将区块移动到画布上来构建布局。
为用户提供可视化方式创建响应式邮件模板——可复用模块、MJML、自定义组件和生产准备的HTML导出,全部在你自己的产品中。
用户所处的循环
26k+
GitHub 星标
100+
GJS.Market 上的插件
10 years
积极开发
BSD-3-Clause
核心许可
打开一个模板,修改它,然后保存为新模板。书架会增加一个。这个循环——而不是单个设计——是邮件模板构建器给用户带来的。
模板库
添加区块
你的标志
欢迎加入,{{ user.first_name }}
以下是启动第一个项目的方法。
打开你的仪表盘
取消订阅 ·管理偏好设置
合并标签保持不动——你的渲染器会在发送时按收件人解析它们。
由GrapesJS项目本身发布的MJML编辑器演示。添加一个部分,编辑文本,然后查看生成的标记。
从演示版自己的网站加载一个iframe。
电子邮件模板构建器允许用户以视觉方式创建和更改邮件布局,而无需手写HTML邮件标记。模板*库*提供完成设计;模板*构建器*提供制作设计的能力——并且在发货后仍能继续制作。
写HTML文件
表格、内联样式、条件注释
跨客户端测试
写作时看不到结果
交给市场部
作为文件,或者粘贴到工具中
每一个变化都会回到你身上
每个调整都要开开发者工单
一个模板,一个所有者,一个瓶颈。
开启起点
从书架上,或者空白
视觉编辑
结果全程都在屏幕上
保存为模板
一排是你客户拥有的
重用与版本
没票就没开发商
很多模板,都是发送者拥有的。
模板为用户提供起点。构建者赋予他们控制权。
图书馆是一个有天花板的书架:它覆盖了它本该覆盖的内容,超过这个线的请求无处可去。建筑者是一个循环——每当有人绕过它,书架就会不断扩大。
“我们需要周五前收到一封干净的欢迎邮件。”
模板库
解决了。这正是好图书馆的意义——选一个,改词,发送。
模板构建器
同样的起点也解决了。建造者船里装有图书馆。
“每个租户都需要自己的法律基础。”
模板库
一个共享的页脚,或者每个租户的模板分支。
模板构建器
一个页脚块,每个租户保存一次,并在他们的模板中重复使用。
“把顾客的实际订单写进收据里。”
模板库
静态占位文本。数据必须在下游拼接。
模板构建器
一个绑定到你的订单模型的组件,可以作为一个模块编辑,并在发送时解决。
“恢复我们上周二发送的版本。”
模板库
你现在看到的是被覆盖的文件。
模板构建器
一个版本行。恢复是一个查询,不是考古项目。
“让我们的客户自己制作,不用给我们发邮件。”
模板库
这不是图书馆的功能——它没有创作界面。
模板构建器
这就是全部的意义。你的用户创建并保存了你从未见过的模板。
把图书馆送到。然后再把能制造更多图书馆的东西送到去。
用户获得的编辑界面,以及你控制的部分。
用户通过按自己想要的顺序将区块移动到画布上来构建布局。
文本、图片和链接会在原地编辑,渲染结果始终显示在屏幕上。
用户保存一次,然后放入任意模板的部分。
在编辑时预览并调整对邮件来说重要的宽度布局。
Author 对抗 mjml,如果你希望响应式标记自动生成,而不是手动维护。
生成你的投递流程已经期望的邮件HTML。
管理模板引用的图片,放在你已经使用的商店里。
添加可编辑组件,镜像你自己产品的数据和工作流程。
完整的历史栈,所以尝试别人的模板是安全的。
给用户一个由多个部分组成的库,而不是让他们从一个空白的画布开始每封邮件。每个都是你注册一次的区块定义。
logo、前置标题文字和导航行(如果你用的话)。
开场陈述和第一次行动号召。
一行或网格的商品绑定到你想要的目录上。
简短的图标和文本行用于发布说明和引导。
规划比较布局,以适应基于表格的渲染器。
一句话,一份署名,还有一个可选的头像。
一个防弹按钮,渲染时没有背景图像。
地址、偏好链接以及你依法必须包含的取消订阅链接。
标准模块覆盖布局。使构建者属于你的是那些知道你数据的组件——订单、订阅、预订、推荐。
标准
每个邮件都需要的原语。它们是编辑器带来的。
作曲
标准的区块,组装一次后注册可重复使用。
绑定
包含用户设定的特征组件,以及渲染器为每个接收者解析的合并标签。
编辑器在模板编写时渲染占位符。你的后端在发送时替换真实值。
// A component bound to your own model. The editor renders a placeholder; your
// backend swaps in the real order at send time, per recipient.
editor.DomComponents.addType('order-summary', {
model: {
defaults: {
droppable: false,
// Traits are the fields the person editing the template can set.
traits: [
{ name: 'orderId', label: 'Order', type: 'text' },
{ name: 'showTax', label: 'Show tax line', type: 'checkbox' },
],
// Merge tags survive export untouched and are resolved by your renderer.
components: '<mj-text>{{ order.total }}</mj-text>',
},
},
});在模板系统中,模板的区别在于谁拥有它,谁可以更改它——不仅仅是它们的文字。这些课程从一开始就值得建模。
所有权等级
这些是模板系统中的所有权类别,不是出售产品。GJS.Market 列出编辑器插件和预设;不销售电子邮件模板。
在编辑时,预览邮件实际渲染的宽度。600px 是正文列的长期惯例——一种惯例,而非规范。
用户可以根据宽度更改哪些内容
桌面客户端上的两列,手机上的叠加——是模板决定的,而不是收件人客户端猜测。
电子邮件客户端实现HTML和CSS的方式不同,且一直如此。可视化构建器并不会消除这一点——它标准化了创作步骤,使每次都能得到相同的已知标记。
| 客户 | 它的不同之处 | 开发商的处理方式 |
|---|---|---|
| Gmail | 在某些情境下剥除<style>的阻断,包括非Gmail账户的Gmail移动应用。 | 发布内衬样式,而不是依赖样式表来完成旅程。 |
| Outlook(Windows) | 用Word引擎渲染时:没有flexbox,没有网格,并且在表格单元格上丢弃了边界半径。 | 生成基于表格的布局和防弹按钮,而不是CSS布局。 |
| 苹果邮件 | 四者中标准最完整;也是最有可能暴露出只有在其他地方偶然才行得通的布局。 | 编辑时预览每个宽度,这样布局是有意为之而非偶然的。 |
| 雅虎邮件 | 历史上与媒体查询不一致;当前行为为Not publicly documented。 | 更倾向于简化为单一可读列且无需媒体查询的布局。 |
约束条件已在2026-08-28上验证。行为变化;检查 caniemail.com 当前状态,并将生产邮件与你自己受众实际使用的客户端进行测试。
mjml 的存在是为了让响应式邮件标记成为你自己生成的,而不是手工维护。GrapesJS 可以用 grapesjs-mjml 扩展,在上面添加可视化的编辑界面。
MJML 足够紧凑,可以在拉取请求中审查,而原始邮件 HTML 则不是。
编译器会发出表支架和媒体查询,所以没有人手写它们。
保持MJML和项目JSON一起,这样模板作为源代码时仍可编辑。
决定你是建造者还是查看者的问题是:用户点击保存后还存在哪些行?三个表格覆盖了这个。
templates
每个模板一行,范围对应租户。
template_versions
仅附录。恢复上周二的邮件需要查询。
blocks
保存一次,之后放进任意模板。
一排版本包含这三者
JSON
项目数据
你加载回编辑器的内容。没有它,模板永远只能读。
MJML
可编辑来源
可调、可复审,编译器改进后可重新编译。
HTML
你发的
渲染和内联,交给你的服务提供者,保持不变。
全部存储三个。每个都回答不同的问题,从其他中的任何一个重建都是有损的。
三种格式的关联编辑器是一个客户端。它向你的 API 请求模板并交还给你;它永远不会知道你的租户是谁,也从不持有任何东西的唯一副本。
模板的归属
// Storage scoped to the tenant AND the template. The editor never learns who
// the tenant is — your API does, from the session, and refuses everything else.
editor.Storage.add('remote', {
async load({ templateId }) {
const res = await fetch(`/api/templates/${templateId}/project`);
return res.json();
},
async store(project, { templateId }) {
await fetch(`/api/templates/${templateId}/project`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(project),
});
},
});把编辑器和你已经运行的后台集成,而不是把邮件流程转移到别人的平台上。GJS.Market卖编辑器插件——它不托管你的模板,也不发送你的邮件。
一旦第二个客户保存模板,所有权就不再是细节。几乎所有产品都分为三层。
属于你的。每个租户都能看到,但没有人能编辑——你维护的起点。
被客户拯救,整个团队都能看到,其他人却看不见。
正在进行中。私密状态,直到有人将其提升为租户模板。
同样的模板系统,指向不同的岗位。
编辑画布是可见的部分。模板系统是其余部分——剩下的就是时间的用处。
模板系统的构成
从零开始
所有这些
使用 GrapesJS
编辑层,已经建好了
GrapesJS 给你提供了编辑层。其上的模板系统——所有权、版本管理、租用——是你的,也应该是:它是匹配你产品的部分。
目录中的真实列表,按模板系统中工作内容分类。名称和价格直接来自市场,因此这里不会偏离实际出售内容。
四个已经可以协同工作的组合,按你构建的模板库选择。
对于各自拥有自己图书馆的客户
嵌入SaaS对于一个团队来说,制作了很多广告活动
对于与你其他内容并存的模板
无头CMS编辑器对于安装在React应用中的编辑器
价格在组装时从目录中实时读取。
GrapesJS 是编辑层,止于 HTML。之后的部分是你的后端和你已经付费的供应商——编辑器里没有内置发送功能,这里也没有任何暗示。
01赛段
发送会引用一个特定版本,所以模板转移后发出的内容依然可复现。
template_versions.id第二赛段
你的渲染器会为每个收件人解析合并标签。编辑器从未看到客户数据。
{{ order.total }}第03赛段
基于表格和内联,这也是每个提供者期望收到的。
text/html第四赛段
无论你已经用的是哪种ESP。更换它不会改变模板系统。
POST /messages第05赛段
打开、点击和跳转都附加在制作版本上,这也是它们可比的原因。
webhook编辑器核心加上官方的MJML插件。两者都是BSD-3-Clause。
npm install grapesjs grapesjs-mjmlimport grapesjs from 'grapesjs';
import grapesjsMjml from 'grapesjs-mjml';
import 'grapesjs/dist/css/grapes.min.css';
// One editor instance per template being edited. The template id — not a page
// id — is what every load and store call is keyed by.
const editor = grapesjs.init({
container: '#template-editor',
plugins: [grapesjsMjml],
pluginsOpts: {
[grapesjsMjml]: {
imagePlaceholderSrc: 'https://cdn.your-app.com/email/placeholder.png',
},
},
storageManager: {
type: 'remote',
autosave: true,
stepsBeforeSave: 10,
},
});保存是模板构建器不再只是编辑者的地方。“保存为模板”创建一行,客户拥有;再次保存是附加版本,而不是覆盖版本。
// "Save as new template" — a row your customer owns from now on.
async function saveAsTemplate(name) {
const res = await fetch('/api/templates', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name,
project: editor.getProjectData(), // re-openable in the editor
}),
});
return res.json(); // { id, name, version: 1 }
}
// Editing an existing template appends a version rather than overwriting it,
// so "restore the version we sent last Tuesday" stays a query, not a restore.
async function saveVersion(templateId) {
await fetch(`/api/templates/${templateId}/versions`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ project: editor.getProjectData() }),
});
}框架细节各自保存在页面上——该页面故意保持框架中立。
需要在产品内部而不是旁边创建邮件的团队。
在应用中嵌入可视化邮件编辑功能,让客户不再导出到另一个工具。
为客户提供一个活动构建器,模板可以进行版本调整、审核和支持。
从可扩展的编辑基础开始,而不是写画布和历史堆栈。
为每个客户构建一个可重复使用的邮件系统,作为模块和锁定模板交给他们。
无需永久拥有编辑器核心及其维护,也能添加邮件创建。
让用户在无需填写标记或提交工单的情况下,直接生成符合品牌的邮件。
本页介绍模板系统。这些模板涵盖了相邻的问题。
从GrapesJS开始,围绕你的产品塑造编辑体验,再用模板系统所需的插件进行扩展。
相关阅读