> ## 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.

# Type Safety

> Generate type-safe PHP enums, DTOs, and Mailables from your Lettr templates in Laravel to catch slug and merge tag errors early

Generate type-safe PHP code from your Lettr templates. Catch errors at compile time instead of runtime.

The SDK provides three Artisan commands that connect to the Lettr API, read your templates and their merge tags, and generate PHP classes you can use in your application. This means your IDE can autocomplete template slugs, enforce required merge tags, and flag typos before you deploy.

## Why Code Generation?

Using string literals for template slugs and merge tags is error-prone:

```php theme={null}
// ❌ Typos cause runtime errors
Mail::lettr()->sendTemplate('welcom-email', 'Welcome!', ['nme' => 'John']);
```

With generated code, your IDE catches mistakes immediately:

```php theme={null}
// ✅ Type-safe, autocomplete-friendly
Mail::lettr()->sendTemplate(
    LettrTemplate::WelcomeEmail->value,
    'Welcome!',
    new WelcomeEmailData(name: 'John')
);
```

The first example silently sends an email with the wrong template slug and missing merge tags. The second example fails at compile time with clear error messages — `LettrTemplate::WelcomEmail` doesn't exist, and `WelcomeEmailData` requires `name`, not `nme`.

## Generate Everything at Once

The `lettr:init` command can generate all code for you during setup:

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

Or generate individually using the commands below.

***

## Template Enum

Generate an enum containing all your template slugs:

```bash theme={null}
php artisan lettr:generate-enum
```

This creates `app/Enums/LettrTemplate.php`:

```php theme={null}
namespace App\Enums;

enum LettrTemplate: string
{
    case WelcomeEmail = 'welcome-email';
    case OrderConfirmation = 'order-confirmation';
    case PasswordReset = 'password-reset';
    case InvoiceReady = 'invoice-ready';
    // ... all your templates
}
```

The command fetches all templates from your Lettr account (using the API key in your `.env`) and generates a backed enum case for each one. The case name is a PascalCase version of the template slug.

### Usage

```php theme={null}
use App\Enums\LettrTemplate;

// IDE autocomplete shows all available templates
Mail::lettr()
    ->to($user->email)
    ->sendTemplate(LettrTemplate::WelcomeEmail->value, 'Welcome!', $data);
```

### Benefits

* **Autocomplete** - Your IDE suggests available templates
* **Refactoring** - Rename templates safely across your codebase
* **Discovery** - See all templates without leaving your editor

***

## Template DTOs

Generate data transfer objects for each template's merge tags:

```bash theme={null}
php artisan lettr:generate-dtos
```

This creates a DTO for each template in `app/Dto/Lettr/`:

```php theme={null}
namespace App\Dto\Lettr;

class WelcomeEmailData
{
    public function __construct(
        public string $first_name,
        public string $activation_url,
        public ?string $company_name = null,
    ) {}

    public function toArray(): array
    {
        return array_filter([
            'first_name' => $this->first_name,
            'activation_url' => $this->activation_url,
            'company_name' => $this->company_name,
        ], fn($v) => $v !== null);
    }
}
```

The command reads each template's merge tags from the Lettr API and generates a DTO class with typed constructor parameters. Required merge tags become required parameters; optional ones get default `null` values. The `toArray()` method strips null values so only provided merge tags are sent.

### Usage

```php theme={null}
use App\Dto\Lettr\WelcomeEmailData;

$data = new WelcomeEmailData(
    first_name: 'John',
    activation_url: $url,
);

Mail::lettr()
    ->to($user->email)
    ->sendTemplate('welcome-email', 'Welcome!', $data->toArray());
```

### Benefits

* **Required fields** - Constructor enforces required merge tags
* **Type hints** - Know exactly what data each template needs
* **Documentation** - DTOs serve as living documentation

<Tip>
  Combine DTOs with the template enum for maximum safety:

  ```php theme={null}
  Mail::lettr()
      ->to($user->email)
      ->sendTemplate(LettrTemplate::WelcomeEmail->value, 'Welcome!', $data->toArray());
  ```
</Tip>

***

## Mailable Classes

Generate Mailable classes for your templates:

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

This creates Mailables in `app/Mail/Lettr/`:

```php theme={null}
namespace App\Mail\Lettr;

use Lettr\Laravel\Mail\LettrMailable;
use Illuminate\Mail\Mailables\Envelope;

class WelcomeEmail extends LettrMailable
{
    public function __construct(
        private string $firstName,
        private string $activationUrl,
    ) {}

    public function envelope(): Envelope
    {
        return new Envelope(
            subject: 'Welcome to Our App',
        );
    }

    public function build(): static
    {
        return $this
            ->template('welcome-email')
            ->substitutionData([
                'first_name' => $this->firstName,
                'activation_url' => $this->activationUrl,
            ]);
    }
}
```

Generated Mailables extend `LettrMailable` and follow standard Laravel conventions. The constructor takes typed parameters for each merge tag, and the `build()` method maps them to the template's substitution data.

### Usage

```php theme={null}
use App\Mail\Lettr\WelcomeEmail;

Mail::to($user->email)->send(
    new WelcomeEmail(
        firstName: $user->first_name,
        activationUrl: $url,
    )
);
```

### Benefits

* **Standard Laravel** - Works with queues, events, and testing
* **Encapsulation** - Template logic stays in one place
* **Familiar API** - Same patterns you already use

***

## Keeping Code in Sync

When you add or modify templates in Lettr, regenerate your code:

```bash theme={null}
# Regenerate enum with new templates
php artisan lettr:generate-enum

# Regenerate DTOs with updated merge tags
php artisan lettr:generate-dtos
```

Generated files are safe to commit to version control. They act as a snapshot of your templates at generation time. If a template is renamed or a merge tag is added in Lettr, the generated code won't update automatically — run the commands again to pick up changes.

<Tip>
  Add these commands to your CI/CD pipeline to ensure code stays in sync with your templates. If the generated output differs from what's committed, you know someone updated a template without regenerating.
</Tip>

### Recommended Workflow

1. Create or update a template in the [Lettr dashboard](https://app.lettr.com/templates)
2. Run `php artisan lettr:generate-enum` and `php artisan lettr:generate-dtos`
3. Commit the generated files
4. Use the enum and DTO in your application code

## Configuration

Customize paths and names in `config/lettr.php`:

```php theme={null}
'templates' => [
    'enum_path' => app_path('Enums'),
    'enum_namespace' => 'App\\Enums',
    'enum_class' => 'LettrTemplate',

    'dto_path' => app_path('Dto/Lettr'),
    'dto_namespace' => 'App\\Dto\\Lettr',

    'mailable_path' => app_path('Mail/Lettr'),
    'mailable_namespace' => 'App\\Mail\\Lettr',
],
```

| Option               | Default          | Description                            |
| -------------------- | ---------------- | -------------------------------------- |
| `enum_path`          | `app/Enums`      | Directory for the generated enum file  |
| `enum_namespace`     | `App\Enums`      | PHP namespace for the enum             |
| `enum_class`         | `LettrTemplate`  | Class name for the generated enum      |
| `dto_path`           | `app/Dto/Lettr`  | Directory for generated DTO files      |
| `dto_namespace`      | `App\Dto\Lettr`  | PHP namespace for DTOs                 |
| `mailable_path`      | `app/Mail/Lettr` | Directory for generated Mailable files |
| `mailable_namespace` | `App\Mail\Lettr` | PHP namespace for Mailables            |

## Artisan Commands Reference

| Command                       | What It Generates                  | Output Location                                     |
| ----------------------------- | ---------------------------------- | --------------------------------------------------- |
| `lettr:init`                  | Enum + DTOs + config (interactive) | Configured paths                                    |
| `lettr:generate-enum`         | Template slug enum                 | `app/Enums/LettrTemplate.php`                       |
| `lettr:generate-dtos`         | Merge tag DTOs                     | `app/Dto/Lettr/`                                    |
| `lettr:pull --with-mailables` | Mailable classes + Blade templates | `app/Mail/Lettr/` + `resources/views/emails/lettr/` |

## What's Next

<CardGroup cols={2}>
  <Card title="Sending Emails" icon="paper-plane" href="/quickstart/laravel/sending-emails">
    Put your generated code to use
  </Card>

  <Card title="Templates" icon="file-code" href="/quickstart/laravel/templates">
    Template versioning, projects, and sync commands
  </Card>

  <Card title="API Reference" icon="book" href="/api-reference/introduction">
    Complete REST API documentation
  </Card>

  <Card title="Best Practices" icon="star" href="/learn/sending/best-practices">
    Sending best practices and deliverability tips
  </Card>
</CardGroup>
