> For the complete documentation index, see [llms.txt](https://codemash.gitbook.io/codemash/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://codemash.gitbook.io/codemash/cloud/emails/templates/editor.md).

# Create or edit a template

Create or edit an email template — name, translations with subject and MJML body, type and tags.

**Where:** Email → Templates → **Create Template → Create New** · `/projects/<project>/emails/templates/new` — or press a template name · `/projects/<project>/emails/templates/<templateId>/edit`

A template holds the content of an email: a subject and an MJML body (a markup that turns into email-safe HTML) for each language, and whether it is a **Marketing** or a **Transactional** email.

## Before you start

* The project languages — at least every one of them needs a translation before campaigns and triggers can use the template ([Project → Settings → Languages](/codemash/cloud/project/settings/languages.md)).
* A [signature](/codemash/cloud/emails/signatures.md) and a [footer](/codemash/cloud/emails/footers.md) if the body renders them (the default body does).
* Permission `email:create` for a new template, `email:update` to save changes.

## Steps

1. Open **Create Template** and choose **Create New**. (**Pick from examples** starts from a ready-made one — see [Start from an example](/codemash/cloud/emails/templates/marketplace.md).)

   <figure><img src="https://712692422-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHy372bqsaex2cqS3ikhL%2Fuploads%2Fgit-blob-15bd4f1852f10f95421de9ffc9f2373cdace306b%2Ftemplates-create-1.png?alt=media" alt="Create Template menu open with Create New and Pick from examples"><figcaption><p>The <strong>Create Template</strong> menu.</p></figcaption></figure>
2. **Add New Email Template** opens with one translation in the project's default language and a default MJML body.

   <figure><img src="https://712692422-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHy372bqsaex2cqS3ikhL%2Fuploads%2Fgit-blob-3d02feefddc05d7b3baa3338b5e34f24d1bfad24%2Ftemplates-create-2.png?alt=media" alt="Add New Email Template: Template name, Description, Translations with EN (default) and DE tags, Language English, Subject"><figcaption><p>The empty form.</p></figcaption></figure>
3. Fill the form:

   | Field                                 | Required | What it does                                                                                                                           | Example                                                  |
   | ------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- |
   | Template name                         | yes      | The name in lists and pickers.                                                                                                         | `Password changed`                                       |
   | Description                           | no       | A note for your team, up to 500 characters.                                                                                            | `Sent by the Membership trigger after a password change` |
   | Translations                          | yes      | Language tags; each picked language adds a block. See [Translate a template](/codemash/cloud/emails/templates/translate.md).           | `EN (default)`                                           |
   | Subject (per language)                | yes      | Plain text with tokens.                                                                                                                | `Your password was changed, @Model.Recipient.FirstName`  |
   | Template (per language)               | yes      | The MJML body, in the code editor or in the full-screen **Template Visual Builder** (**Edit in Visual Builder →**).                    | the default body                                         |
   | Marketing Email / Transactional Email | yes      | Marketing emails get preferences and unsubscribe links and respect a recipient's unsubscribe; transactional ones are always delivered. | Transactional Email                                      |
   | Marketing Tags / Transactional Tags   | no       | Topics a recipient can turn off one by one.                                                                                            | `Account Alerts`                                         |

   <figure><img src="https://712692422-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHy372bqsaex2cqS3ikhL%2Fuploads%2Fgit-blob-59a33a8d829b9ce16cc41a4801e524624c1eb9b3%2Ftemplates-create-3.png?alt=media" alt="Template name Password changed, Description filled, Subject Your password was changed, @Model.Recipient.FirstName"><figcaption><p>Name, description and subject filled.</p></figcaption></figure>

   <figure><img src="https://712692422-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHy372bqsaex2cqS3ikhL%2Fuploads%2Fgit-blob-2567c096ad18d03a820611b83c6a45e4015a62ac%2Ftemplates-create-4.png?alt=media" alt="The end of the form: Marketing Email and Transactional Email (selected), Transactional Tags chips, Cancel and Create buttons"><figcaption><p>Type, tags and <strong>Create</strong>.</p></figcaption></figure>
4. Press **Create** (a new template) or **Update** (an existing one).

## Result

When Norbix has saved it you are back on the list, and the template is there. A template that misses a project language shows **Missing de**.

<figure><img src="https://712692422-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHy372bqsaex2cqS3ikhL%2Fuploads%2Fgit-blob-680a95ec091c54a6d3f2c3ea487ace23ad978a94%2Ftemplates-create-5.png?alt=media" alt="Email Templates list with Password changed on top, Transactional, Is Active Yes, Missing de"><figcaption><p>The new template in the list.</p></figcaption></figure>

Open it again to edit it. The id is shown as a copy button (`tmpl_3pLex0vXrqcLzOsJP8VLRx`), and **Test** and **Actions** sit in the top right. Every send that points at this id uses the new content from the next send on.

<figure><img src="https://712692422-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHy372bqsaex2cqS3ikhL%2Fuploads%2Fgit-blob-8b50cedee5a37d3e26f6c9d829840cb06eecec4c%2Ftemplates-edit-1.png?alt=media" alt="Edit Email Template for Welcome email: id copy button, Template name, Description, Translations EN (default) and DE, Test and Actions buttons"><figcaption><p>An existing template in the editor.</p></figcaption></figure>

**Edit in Visual Builder →** opens the **Template Visual Builder**: a **Test Tokens Panel** (pick a trigger type and type token values) above the code and a live preview. The values there are only for the preview; they are not saved.

<figure><img src="https://712692422-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHy372bqsaex2cqS3ikhL%2Fuploads%2Fgit-blob-5f8e66f57bbd2e5375640d63ac000820e240398c%2Ftemplates-edit-4.png?alt=media" alt="Template Visual Builder: Test Tokens Panel with Trigger Type Not a trigger and token inputs, a list of missing tokens, the code and the rendered preview Welcome to Acme"><figcaption><p>The Template Visual Builder.</p></figcaption></figure>

Useful calls in a body: `@Model.Cmf.WriteSalutation("Hi", Model.Recipient.FirstName)`, `@Model.Cmf.RenderSignature(Model.Email.SignatureId)`, `@Model.Cmf.RenderFooter(Model.Email.FooterId)`, `@Model.Cmf.GetEmailPreferencesLink()` and `@Model.Cmf.GetEmailUnsubscribeFromCategoryLink()` ([preferences and unsubscribe pages](/codemash/cloud/emails/preferences.md)). Only allow-listed `@Model.Cmf.…` functions compile. Tokens are HTML-encoded; use `@Raw(...)` only for HTML you trust. MJML that cannot be turned into HTML is never sent: the send fails with `CM-ERRORS-EMAILS-023`.

## Change or remove it later

**Actions** on a saved template (the items are off while the form has unsaved changes):

<figure><img src="https://712692422-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHy372bqsaex2cqS3ikhL%2Fuploads%2Fgit-blob-11b749126133a879cb819537bad6a90b05cf1c36%2Ftemplates-edit-2.png?alt=media" alt="Actions menu: Create Campaign, Archive, Unarchive (off), Clone, See documentation, Delete"><figcaption><p>The Actions menu of a template.</p></figcaption></figure>

* **Create Campaign** — opens [the campaign form](/codemash/cloud/emails/campaigns/new.md) with this template picked.
* **Archive** / **Unarchive** — take it out of use, or bring it back: [Publish, archive, unarchive](/codemash/cloud/emails/templates/publish.md).
* **Clone** — makes a copy with the same name and content; rename the copy.
* **Delete** — [Delete a template](/codemash/cloud/emails/templates/delete.md).
* **Test** — [Send a test](/codemash/cloud/emails/templates/test-send.md).

A template used by a trigger or an authentication flow cannot be deleted or archived — see [Message templates](/codemash/cloud/concepts/message-templates.md).

## Do it from code

```ts
const { id } = await norbix.hub.notifications.createEmailTemplate({
  templateName: 'Account locked',
  description: 'Sent after five failed sign-ins',
  communicationChannel: 'Transactional',
  translations: [
    { language: 'en', content: { subject: 'Your account is locked', body: { code: '<mjml><mj-body><mj-section><mj-column><mj-text>Hi @Model.Recipient.FirstName, your account is locked for 15 minutes.</mj-text></mj-column></mj-section></mj-body></mjml>' } } },
    { language: 'de', content: { subject: 'Ihr Konto ist gesperrt', body: { code: '<mjml><mj-body><mj-section><mj-column><mj-text>Hallo @Model.Recipient.FirstName, Ihr Konto ist für 15 Minuten gesperrt.</mj-text></mj-column></mj-section></mj-body></mjml>' } } },
  ],
});
console.log(id); // tmpl_…
```

```sh
norbix hub notifications email template get --id tmpl_3pLex0vXrqcLzOsJP8VLRx
```

To change a template, send the whole template back with `updateEmailTemplate` (`viewId`, `templateName`, `communicationChannel`, `translations`) — see [Translate a template](/codemash/cloud/emails/templates/translate.md#do-it-from-code).

API: [Create Email Template](/codemash/api-reference/notifications/email/create-email-template.md) · [Update Email Template](/codemash/api-reference/notifications/email/update-email-template.md) · [Get Email Template](/codemash/api-reference/notifications/email/get-email-template.md) · [Clone Email Template](/codemash/api-reference/notifications/email/clone-email-template.md)
