PHPackages                             goldnead/statamic-email-templates - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Mail &amp; Notifications](/categories/mail)
4. /
5. goldnead/statamic-email-templates

ActiveStatamic-addon[Mail &amp; Notifications](/categories/mail)

goldnead/statamic-email-templates
=================================

Statamic 6 Email Templates — CP-native, Bard-authored email templates in a shared collection, consumed optionally by statamic-automations and statamic-marketing.

v1.3.0(today)00MITPHPPHP ^8.2CI passing

Since Jul 18Pushed todayCompare

[ Source](https://github.com/goldnead/statamic-email-templates)[ Packagist](https://packagist.org/packages/goldnead/statamic-email-templates)[ Docs](https://github.com/goldnead/statamic-email-templates)[ RSS](/packages/goldnead-statamic-email-templates/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (8)Versions (13)Used By (0)

Statamic Email Templates
========================

[](#statamic-email-templates)

> Write your transactional and marketing emails in the Control Panel you already use.

Email Templates gives Statamic a managed `et_templates` collection: your emails are ordinary entries, authored in Bard, edited in the native publish form, and previewed with Statamic's own Live Preview while you type. Other code — your app, a queued job, a sibling addon — asks for a template by slug and gets ready-to-send HTML back.

The addon ships **no Control Panel screens of its own**. The listing, the editor, search, filters, sorting, permissions, localisation and dark mode are core's.

Requirements
------------

[](#requirements)

Statamic6.0+PHP8.2+Laravel12.40+ or 13 (whatever Statamic 6 pulls in)Databasenot required — templates are flat-file entriesInstallation
------------

[](#installation)

```
composer require goldnead/statamic-email-templates

```

That is the whole setup. On the next request the addon creates the `et_templates`collection and its blueprint, and adds **Email templates** to the *Content* section of the CP nav. Open it and press *Create Entry*.

To publish the config file:

```
php artisan vendor:publish --tag=email-templates-config

```

Usage
-----

[](#usage)

### Authoring

[](#authoring)

Each template entry has:

FieldWhat it is`title`Internal name, shown in the listing`slug`**The stable reference.** Code looks templates up by this and it is never rewritten`subject`The email subject line. Merge variables allowed`preview`Preheader text — the line inbox clients show next to the subject`layout`Which configured shell wraps this template (see *Configuration*)`body`The email itself, as Bard`plain_text`Optional `text/plain` alternative`description`A note to your future self### Reading a template from code

[](#reading-a-template-from-code)

```
use Goldnead\EmailTemplates\Facades\EmailTemplates;

$template = EmailTemplates::resolve('welcome');

$template?->subject;    // string, merge tags not yet substituted
$template?->body;       // email-ready HTML
$template?->plain_text; // string|null
```

`resolve()` takes an optional fallback for slugs that have not been migrated into the collection yet. A managed entry always wins:

```
$template = EmailTemplates::resolve($slug, function (string $slug) {
    return ['title' => '…', 'body' => '…']; // or null
});
```

### Merge variables

[](#merge-variables)

Templates use `{{ dotted.key }}` placeholders in the subject, the preheader and the body. At send time your code supplies real recipient data; the CP preview supplies a documented sample set, so a template can be previewed without a real contact.

```
use Goldnead\EmailTemplates\Support\MergeVariables;

$subject = MergeVariables::apply($template->subject, [
    'contact' => ['first_name' => $user->first_name],
]);
```

Unknown tags are **left visible** rather than silently removed, so a typo shows up in the preview instead of in someone's inbox. Values are inserted verbatim, without HTML escaping — sanitise recipient-controlled data before you pass it in.

The default sample set, overridable via `email-templates.preview.sample_data`:

VariableSample value`{{ contact.first_name }}``Maria``{{ contact.last_name }}``Beispiel``{{ contact.full_name }}``Maria Beispiel``{{ contact.email }}``maria.beispiel@example.com``{{ contact.salutation }}``Hallo Maria``{{ sender.name }}``config('mail.from.name')``{{ sender.email }}``config('mail.from.address')``{{ unsubscribe_url }}``https://example.com/newsletter/abmelden``{{ date }}`today, `d.m.Y`### Live Preview

[](#live-preview)

Open a template and press Statamic's Live Preview button: the split-screen renders the actual email — Bard to HTML, merge variables substituted, wrapped in the layout that would really wrap it — and updates as you type.

Email templates are not web pages, so the collection has **no front-end route**. Entries are instantiated as `EmailTemplateEntry`, which enables the Live Preview button without giving templates a public URL. The split-screen iframe is served by `GET /email-templates/live-preview`, which only renders a body for a valid, short-lived Live Preview token and shows a neutral placeholder otherwise.

Configuration
-------------

[](#configuration)

`config/email-templates.php`:

KeyDefaultWhat it does`enabled``true`Master switch. `false` stops the addon creating the collection and adding the nav item. The resolver and the import command stay callable.`branded_layout``null`A Blade view that wraps every rendered body — your header, footer and styling. It must contain `@yield('content')`; the subject arrives as `$title`. `null` renders bodies unwrapped.`layouts``[]`A `handle => view` map. The keys populate the `layout` select on each entry, so a transactional mail can pick a lean shell and a campaign a marketing one.`default_layout``null`A handle from `layouts`, used for entries that pick none.`preview.sample_data`see aboveDeep-merged over the built-in merge-variable sample set.Layout resolution for an entry: its own `layout`, else `default_layout`, else `branded_layout`. An unknown handle or a missing view falls through the chain — nothing throws mid-send.

Permissions
-----------

[](#permissions)

The addon registers **no permissions of its own**. Access is governed entirely by the collection's native permissions, which Statamic generates:

- `view et_templates entries` — controls the nav item and the listing
- `edit et_templates entries`, `create et_templates entries`, `delete et_templates entries`

Grant them under *Users → Roles* like any other collection. A role without `view et_templates entries` does not see the nav item.

Multi-site
----------

[](#multi-site)

Templates are shared across sites, and the wording is localisable per site: `title`, `subject`, `preview`, `body` and `plain_text` are localisable fields; `layout` is not, because which shell wraps a template is a structural decision, not a translation.

Brands
------

[](#brands)

Unlike the other addons in this family, templates carry **no brand scope**. In a multi-brand installation all brands share one set of templates. If you need different shells per brand, model that with `layouts` rather than duplicating templates.

Blueprint and collection ownership
----------------------------------

[](#blueprint-and-collection-ownership)

The addon owns the *existence* of the `et_templates` collection and its blueprint, not their contents. Boot is a create-if-missing pass: once you edit the blueprint in the CP — adding fields, reordering, renaming the collection — those edits stay. The addon only writes when something is actually missing, and it will not overwrite your changes.

The one thing it does reclaim: a collection carrying the placeholder front-end route `_email-template-preview/{slug}` written by v1.2.1 and earlier has that route removed, because `EmailTemplateEntry` replaced it. A route you set yourself is left alone.

If the addon cannot write to your content directory it logs a warning and carries on rather than breaking the request. Check `storage/logs` if the collection does not appear.

Importing existing templates
----------------------------

[](#importing-existing-templates)

If your emails currently live in files, import them once. Slugs are preserved 1:1, so anything already referencing a template by slug keeps working:

```
php artisan email-templates:import --dry-run
php artisan email-templates:import

```

OptionEffect`--dry-run`Report what would happen, write nothing`--overwrite`Replace entries whose slug already exists (default: skip)`--source=`Only import from the source with this label### Contributing an import source

[](#contributing-an-import-source)

Implement the contract and tag it — the command picks it up without any change here:

```
use Goldnead\EmailTemplates\Contracts\EmailTemplateSource;

$this->app->tag([MySource::class], 'email-templates.sources');
```

How Bard becomes email HTML
---------------------------

[](#how-bard-becomes-email-html)

The body is stored as Bard (ProseMirror nodes) and rendered to HTML at send and preview time by `BardHtmlRenderer` — one path, so the preview and the real email are produced identically. Imported HTML is converted to Bard nodes by `HtmlToBard`.

**Fidelity note:** tiptap's schema keeps structural markup (headings, lists, links, images, tables) and drops inline styles and unknown attributes. Simple transactional templates round-trip cleanly; heavily styled legacy marketing HTML may lose styling. Put the styling in a layout rather than in the body.

Support
-------

[](#support)

Only the latest release is supported, against Statamic 6. Bugs and questions go to [GitHub issues](https://github.com/goldnead/statamic-email-templates/issues); security reports go to the private channel in [SECURITY.md](SECURITY.md). Problems with the Control Panel itself belong in [statamic/cms](https://github.com/statamic/cms/issues).

Changelog · License
-------------------

[](#changelog--license)

See [CHANGELOG.md](CHANGELOG.md) and [LICENSE.md](LICENSE.md) (MIT).

###  Health Score

42

—

FairBetter than 88% of packages

Maintenance100

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 95.8% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

12

Last Release

0d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/85572d690277234a86834808cab169c4900922b4855fe9028426f8350dd74e97?d=identicon)[goldnead](/maintainers/goldnead)

---

Top Contributors

[![goldnead](https://avatars.githubusercontent.com/u/1313348?v=4)](https://github.com/goldnead "goldnead (23 commits)")[![goldner-chief](https://avatars.githubusercontent.com/u/305460866?v=4)](https://github.com/goldner-chief "goldner-chief (1 commits)")

---

Tags

automationemailtemplatesstatamicStatamic addon

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/goldnead-statamic-email-templates/health.svg)

```
[![Health](https://phpackages.com/badges/goldnead-statamic-email-templates/health.svg)](https://phpackages.com/packages/goldnead-statamic-email-templates)
```

###  Alternatives

[propaganistas/laravel-disposable-email

Disposable email validator

6023.2M7](/packages/propaganistas-laravel-disposable-email)[laravel/sail

Docker files for running a basic Laravel application.

1.9k212.4M1.4k](/packages/laravel-sail)[laravel/ai

The official AI SDK for Laravel.

1.1k4.6M275](/packages/laravel-ai)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

78727.1M205](/packages/laravel-mcp)[erag/laravel-disposable-email

A Laravel package to detect and block disposable email addresses.

265192.2k](/packages/erag-laravel-disposable-email)[tallstackui/tallstackui

TallStackUI is a powerful suite of Blade components that elevate your workflow of Livewire applications.

729176.2k16](/packages/tallstackui-tallstackui)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
