enflow/livewire-twig
Integrates Twig templating with Laravel Livewire, letting components render Twig views while retaining Livewire’s reactive behavior. Ideal for Laravel projects or teams already standardized on Twig-style templates.
Install the package alongside Livewire and the Twig bridge:
composer require enflow/livewire-twig
Twig templates for components live in your configured Twig view paths (typically resources/views, same as Blade — the engine is selected by file extension .twig). Point a Livewire component at a Twig view by returning it from render() exactly as you would with Blade:
class Counter extends Component
{
public $count = 0;
public function increment() { $this->count++; }
public function render()
{
return view('livewire.counter'); // resolves counter.twig
}
}
<div>
<button wire:click="increment">+</button>
<span>{{ count }}</span>
</div>
First things to check:
config/livewire-twig.php (publish with php artisan vendor:publish --tag=livewire-twig-config) — it controls template paths and extension registration.wire:* directives are bridged into Twig.wire:model, wire:click, and nested components, since those are the patterns you'll reuse most.Since 4.6.0 is a minor bump from 4.5.0 with no breaking-change signals in the changelog, this is a safe starting point.
Component → Twig view mapping. Keep the extension-based resolution (counter.twig) rather than forcing explicit paths; it lets you mix Blade and Twig components in the same app, which is common during incremental migrations.
Directive usage. Livewire directives are exposed as Twig constructs. In practice you write them the same way you would in Blade:
<input wire:model="search" type="text">
<button wire:click="save" wire:loading.attr="disabled">Save</button>
Shared Twig extensions. Register your own Twig filters/functions in the same service provider where Livewire's extensions are wired, so app-wide Twig helpers (money formatting, date formatting) are available inside Livewire-rendered templates too.
Layouts and slots. Use Twig {% extends %} / {% block %} for page layout, but keep component partials as flat files — Livewire's partial re-render expects the component root to be a single template, not an inherited one.
Nested components. Reference child components with the same <livewire:child /> tag or @livewire equivalent the package exposes; verify rendering after any minor upgrade since the directive bridge is the most upgrade-sensitive surface.
Testing. Use Livewire's standard Livewire::test() API — the fact that the view is Twig rather than Blade is transparent to assertions, so existing test patterns carry over.
{{ }}. If you rely on Livewire outputting raw HTML (e.g. {!! !!} in Blade), you need {{ value|raw }} in Twig. This is the most common source of "my markup is showing as text" bugs.: inside attributes (e.g. x-on:click, wire:model.defer). Wrap problematic attributes in single quotes or use {{ }} interpolation carefully — Alpine's : syntax can collide with Twig's object-access syntax.wire:* usages (especially modifiers like .defer, .live, .debounce) against the release after upgrading.php artisan view:clear — stale Twig cache is a frequent cause of "changes didn't take effect."view('livewire.counter')->render()) to isolate whether the failure is Twig parsing or Livewire lifecycle.^4.6 and read the GitHub compare diff before bumping to 4.7+; treat minor bumps as potentially touching the directive bridge even though semver says otherwise.How can I help you explore Laravel packages today?