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:
// ❌ Typos cause runtime errors
Mail::lettr()->sendTemplate('welcom-email', 'Welcome!', ['nme' => 'John']);
With generated code, your IDE catches mistakes immediately:
// ✅ 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:
Or generate individually using the commands below.
Template Enum
Generate an enum containing all your template slugs:
php artisan lettr:generate-enum
This creates app/Enums/LettrTemplate.php:
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
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:
php artisan lettr:generate-dtos
This creates a DTO for each template in app/Dto/Lettr/:
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
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
Combine DTOs with the template enum for maximum safety:Mail::lettr()
->to($user->email)
->sendTemplate(LettrTemplate::WelcomeEmail->value, 'Welcome!', $data->toArray());
Mailable Classes
Generate Mailable classes for your templates:
php artisan lettr:pull --with-mailables
This creates Mailables in app/Mail/Lettr/:
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
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:
# 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.
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.
Recommended Workflow
- Create or update a template in the Lettr dashboard
- Run
php artisan lettr:generate-enum and php artisan lettr:generate-dtos
- Commit the generated files
- Use the enum and DTO in your application code
Configuration
Customize paths and names in config/lettr.php:
'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