> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lettr.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Templates

> Send Lettr templates with merge tags from Laravel, plus versioning, projects, and syncing templates with your local codebase

Lettr templates let you manage email designs in the Lettr dashboard while your application provides the dynamic data. This separation means designers can update email layouts without touching application code, and developers can change data without worrying about design.

This page covers sending templates, versioning, projects, and syncing templates between Lettr and your local codebase. For type-safe template usage with generated enums and DTOs, see [Type Safety](/quickstart/laravel/type-safety).

## Sending with Templates

The simplest way to send a template:

```php theme={null}
use Illuminate\Support\Facades\Mail;

Mail::lettr()
    ->to('user@example.com')
    ->sendTemplate('welcome-email', 'Welcome!', [
        'first_name' => 'John',
        'activation_url' => 'https://example.com/activate/abc123',
    ]);
```

The array keys correspond to merge tags in your template (e.g., `{{first_name}}`). If a required merge tag is missing from the array, the tag renders as an empty string in the sent email. See [Merge Tags & Template Language](/learn/templates/template-language) for the full syntax including conditionals and loops.

## Type-Safe Templates

Generate enums, DTOs, and Mailable classes from your templates for compile-time safety:

```bash theme={null}
php artisan lettr:generate-enum   # Template slug enum
php artisan lettr:generate-dtos   # Merge tag DTOs
```

This catches typos in template slugs and missing merge tags at compile time rather than in production.

<Card title="Type Safety" icon="shield-check" href="/quickstart/laravel/type-safety">
  Generate enums, DTOs, and Mailables for compile-time safety
</Card>

## Template Versioning

Specify a template version to use a specific iteration:

```php theme={null}
Mail::lettr()
    ->to('user@example.com')
    ->sendTemplate(
        templateSlug: 'welcome-email',
        subject: 'Welcome!',
        substitutionData: $data,
        version: 2  // Use version 2 of the template
    );
```

Omit the version to use the active (published) version.

**When to use versioning:**

* **Production safety** — Pin to a known-good version so publishing a new draft doesn't affect live emails
* **A/B testing** — Send different versions to different cohorts and compare metrics in [Analytics](/learn/analytics/introduction)
* **Gradual rollout** — Test a new version with a subset of users before publishing it as the active version

See [Versions](/learn/templates/versions) for how versioning works in the Lettr dashboard.

## Pull Templates Locally

Download templates from Lettr to edit locally as Blade files:

```bash theme={null}
php artisan lettr:pull
```

Options:

* `--template=slug` - Pull a specific template. Exits with a failure code if it doesn't exist
* `--as-html` - Save as HTML instead of Blade
* `--with-mailables` - Also generate Mailable and DTO classes
* `--skip-templates` - With `--with-mailables`, generate only DTOs and Mailables, without downloading templates
* `--dry-run` - Preview what would be downloaded without writing files

By default, templates are saved as Blade files to `resources/views/emails/lettr/`. HTML files go to `resources/templates/lettr/`. Both paths are configurable in `config/lettr.php`.

When converting to Blade, merge tags become variables (`{{first_name}}` → `{{ $first_name }}`) and loops become null-safe `@foreach` blocks whose items are read as arrays (`{{#each items}}{{this.name}}` → `@foreach($items ?? [] as $item){{ $item['name'] }}`), which is the shape generated DTOs pass to the view.

<Tip>
  Use `--with-mailables` to generate ready-to-use Mailable classes alongside the templates. This is the fastest way to scaffold email classes from your existing Lettr templates. See [Mailable Classes](/quickstart/laravel/type-safety#mailable-classes) for the two kinds of Mailable it can generate.
</Tip>

## Push Templates to Lettr

Upload local Blade templates to Lettr, creating them if they do not exist:

```bash theme={null}
php artisan lettr:push
```

Without `--path`, the command looks for templates in `blade_path` from `config/lettr.php` (where `lettr:pull` saves them), then in `resources/views/emails`, `mails`, `email` and `mail`, and asks before using a folder.

Options:

* `--path=` - Custom path to the templates directory, absolute or relative to your project root
* `--template=filename` - Push only one template
* `--purpose=` - Module to create the templates in: `transactional` (default) or `campaign`
* `--dry-run` - Preview what would be created without pushing

To push marketing templates that campaigns can pick:

```bash theme={null}
php artisan lettr:push --purpose=campaign
```

<Warning>
  **`purpose` applies to templates being created, and cannot be changed afterwards.** Push without it and you get transactional templates, which a [campaign](/learn/campaigns/introduction) cannot use — the update endpoint does not accept `purpose`, so the only remedy is to copy each one in the app. Pushing a newsletter set? Pass `--purpose=campaign` the first time. See [Transactional vs. Marketing Templates](/learn/templates/projects#transactional-vs-marketing-templates).
</Warning>

## Listing Templates

Retrieve available templates via the API:

```php theme={null}
use Lettr\Laravel\Facades\Lettr;

$response = Lettr::templates()->list();

foreach ($response->templates as $template) {
    echo $template->name . ' (' . $template->slug . ')';
}
```

Get a specific template and its merge tags:

```php theme={null}
$template = Lettr::templates()->get('welcome-email');

echo $template->name;
echo $template->activeVersion;

$response = Lettr::templates()->getMergeTags('welcome-email', version: $template->activeVersion);

foreach ($response->mergeTags as $mergeTag) {
    echo $mergeTag->key . ($mergeTag->required ? ' (required)' : '');
}
```

Each merge tag has a `key`, a `required` flag, a `type`, and `children` for loop blocks, which is useful for validating your substitution data before sending.

## What's Next

<CardGroup cols={2}>
  <Card title="Type Safety" icon="shield-check" href="/quickstart/laravel/type-safety">
    Generate enums, DTOs, and Mailables for compile-time safety
  </Card>

  <Card title="Template Language" icon="code" href="/learn/templates/template-language">
    Full merge tag syntax including conditionals and loops
  </Card>

  <Card title="Projects & Folders" icon="folder" href="/learn/templates/projects">
    Organize templates into projects
  </Card>

  <Card title="Topol Editor" icon="paintbrush" href="/learn/templates/topol-editor">
    Design templates visually in the Lettr dashboard
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.