twig/inky-extra
Twig extension adding an inky_to_html filter to convert ZURB Inky email templates into responsive HTML. Useful for generating email markup from simple Inky components directly within Twig templates.
composer require twig/inky-extra
spatie/laravel-twig): Automatic.$twig->addExtension(new \Twig\Extra\Inky\InkyExtension());
resources/views/emails/welcome.inky):
<container>
<row>
<columns large="6">
<h1>Welcome, {{ name }}!</h1>
<p>Thanks for signing up.</p>
</columns>
</row>
</container>
{% set name = "John" %}
{{ include('emails/welcome.inky', {'name': name}) | inky_to_html }}
Replace a manual HTML email template with an Inky template for a password reset email:
<!-- resources/views/emails/reset_password.inky -->
<container>
<row>
<columns large="8">
<h1>Reset Your Password</h1>
<p>Click the button below to reset your password:</p>
<button>{{ reset_link }}</button>
<p>If you didn't request this, ignore this email.</p>
</columns>
</row>
</container>
Render it in a Laravel Mailable:
public function build()
{
return $this->markdown('emails.reset_password')
->with([
'reset_link' => $this->resetLink,
]);
}
Update the Twig template (resources/views/emails/reset_password.blade.php):
{{ include('emails/reset_password.inky', {'reset_link': reset_link}) | inky_to_html }}
Use Twig macros to create reusable email components (e.g., headers, footers):
{% macro header(title) %}
<container>
<row>
<columns large="12">
<h1>{{ title }}</h1>
</columns>
</row>
</container>
{% endmacro %}
{% macro footer() %}
<container>
<row>
<columns large="12">
<p>© {{ year }} Your Company. All rights reserved.</p>
</columns>
</row>
</container>
{% endmacro %}
Include them in your Inky templates:
{{ include('emails/_macros.inky') }}
{{ header('Welcome!') }}
<row>
<columns large="6">
<p>Your content here.</p>
</columns>
</row>
{{ footer() }}
Combine Twig logic with Inky templates for conditional content:
{% set user = App\Models\User::find(1) %}
{% set is_premium = user->is_premium %}
{{ include('emails/welcome.inky', {
'name': user.name,
'is_premium': is_premium ? 'true' : 'false'
}) | inky_to_html }}
In your Inky template (welcome.inky):
{% if is_premium == 'true' %}
<row>
<columns large="12">
<p>Enjoy your premium features!</p>
</columns>
</row>
{% endif %}
Create multiple Inky templates (e.g., welcome_variant_a.inky, welcome_variant_b.inky) and select them dynamically:
{% set variant = 'a' %} {# or fetch from database #}
{% set template = 'emails/welcome_variant_' ~ variant ~ '.inky' %}
{{ include(template, {'name': user.name}) | inky_to_html }}
Extend Laravel’s Mailable class to support Inky templates:
use Twig\Extra\Inky\InkyExtension;
class InkyMailable extends Mailable
{
public function build()
{
return $this->twig('emails.welcome', [
'name' => $this->name,
]);
}
protected function getTwig()
{
$twig = parent::getTwig();
$twig->addExtension(new InkyExtension());
return $twig;
}
}
.inky files (e.g., resources/views/emails/).inky_to_html filter converts them to HTML on-the-fly.Add a step to test email rendering in your pipeline:
# .github/workflows/test-emails.yml
jobs:
test-emails:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm install -g mjml
- run: |
# Convert Inky to HTML and validate
php artisan twig:render emails/welcome.inky --data='{"name":"Test"}' > welcome.html
mjml welcome.html --no-validate
Cache rendered HTML for high-volume emails (e.g., newsletters):
// In your Mailable or controller
$html = Cache::remember("email-welcome-{$user->id}", now()->addHours(1), function () use ($user) {
return view('emails.welcome', ['user' => $user])->render();
});
spatie/laravel-twig for seamless Twig integration in Laravel.Mailable classes to encapsulate email logic and Inky rendering.Mail::to($user)->queue(new InkyMailable($user));
# config/packages/twig.yaml
twig:
extensions:
- Twig\Extra\Inky\InkyExtension
Swiftmailer or Mailer component to send emails:
$message = (new \Symfony\Component\Mailer\Email())
->to($user->email)
->subject('Welcome!')
->html($twig->render('emails/welcome.inky', ['name' => $user->name]))
->text($twig->render('emails/welcome.txt', ['name' => $user->name]));
$mailer->send($message);
public function testWelcomeEmail()
{
$twig = $this->app->make('twig');
$html = $twig->render('emails/welcome.inky', ['name' => 'John']);
$this->assertStringContainsString('Welcome, John!', $html);
}
{{ }} syntax conflicts with Twig’s variable interpolation. Raw Inky strings must be pre-processed.inky_to_html filter:
{% set name = "John" %}
{{ include('emails/welcome.inky', {'name': name}) | inky_to_html }}
Avoid:
{{ include('emails/welcome.inky') | inky_to_html }} {# This won't work for dynamic content #}
<container>, <row>).How can I help you explore Laravel packages today?