SKILL.md
Livewire Development
When to Apply
Activate this skill when:
- Creating or modifying Livewire components
- Using wire: directives (model, click, loading, sort, intersect)
- Implementing islands or async actions
- Writing Livewire component tests
Documentation
Use search-docs for detailed Livewire 4 patterns and documentation.
Basic Usage
Creating Components
Single-file component (default in v4)
{{ $assist->artisanCommand('make:livewire create-post') }}
Multi-file component
{{ $assist->artisanCommand('make:livewire create-post --mfc') }}
Class-based component (v3 style)
{{ $assist->artisanCommand('make:livewire create-post --class') }}
With namespace
{{ $assist->artisanCommand('make:livewire Posts/CreatePost') }}
Converting Between Formats
Use php artisan livewire:convert create-post to convert between single-file, multi-file, and class-based formats.
Component Format Reference
Format
Flag
Structure
Single-file (SFC)
default
PHP + Blade in one file
Multi-file (MFC)
--mfc
Separate PHP class, Blade, JS, tests
Class-based
--class
Traditional v3 style class
View-based
⚡ prefix
Blade-only with functional state
Single-File Component Example
Livewire 4 Specifics
Key Changes From Livewire 3
These things changed in Livewire 4, but may not have been updated in this application. Verify this application's setup to ensure you follow existing conventions.
- Use
Route::livewire()for full-page components; config keys renamed:layout→component_layout,lazy_placeholder→component_placeholder.
wire:modelnow ignores child events by default (usewire:model.deepfor old behavior);wire:scrollrenamed towire:navigate:scroll.
- Component tags must be properly closed;
wire:transitionnow uses View Transitions API (modifiers removed).
- JavaScript:
$wire.$js('name', fn)→$wire.$js.name = fn;commit/requesthooks →interceptMessage()/interceptRequest().
New Features
- Component formats: single-file (SFC), multi-file (MFC), view-based components.
- Islands (
@island) for isolated updates; async actions (wire:click.async,#[Async]) for parallel execution.
- Deferred/bundled loading:
defer,lazy.bundlefor optimized component loading.
Feature
Usage
Purpose
Islands
@island(name: 'stats')
Isolated update regions
Async
wire:click.async or #[Async]
Non-blocking actions
Deferred
defer attribute
Load after page render
Bundled
lazy.bundle
Load multiple together
New Directives
wire:sort,wire:intersect,wire:ref,.renderless,.preserve-scrollare available for use.
data-loadingattribute automatically added to elements triggering network requests.
Directive
Purpose
wire:sort
Drag-and-drop sorting
wire:intersect
Viewport intersection detection
wire:ref
Element references for JS
.renderless
Component without rendering
.preserve-scroll
Preserve scroll position
Best Practices
- Always use
wire:keyin loops
- Use
wire:loadingfor loading states
- Use
wire:model.livefor instant updates (default is debounced)
- Validate and authorize in actions (treat like HTTP requests)
Configuration
smart_wire_keysdefaults totrue; new configs:component_locations,component_namespaces,make_command,csp_safe.
Alpine & JavaScript
wire:transitionuses browser View Transitions API;$errorsand$interceptmagic properties available.
- Non-blocking
wire:polland parallelwire:model.liveupdates improve performance.
For interceptors and hooks, see reference/javascript-hooks.md.
Testing
Livewire::test(Counter::class)
->assertSet('count', 0)
->call('increment')
->assertSet('count', 1);
Verification
- Browser console: Check for JS errors
- Network tab: Verify Livewire requests return 200
- Ensure
wire:keyon all@foreachloops
Common Pitfalls
- Missing
wire:keyin loops → unexpected re-rendering
- Expecting
wire:modelreal-time → usewire:model.live
- Unclosed component tags → syntax errors in v4
- Using deprecated config keys or JS hooks
- Including Alpine.js separately (already bundled in Livewire 4)