model_tier: medium
name: livewire
description: "Use when the project's frontend stack is Livewire — dispatched by directives/ui/{apply,review,polish}.py. Covers reactive state, events, lifecycle hooks, and component/view separation."
domain: engineering
workspaces:
- engineering
packs:
- laravel
trust:
level: professional
install:
default: false
removable: true
livewire
Grounded stack guidance: pull idiomatic Blade/UI Do/Don't + docs URLs via
ground.py search --manifest <skills-root>/design-intelligence/data/manifest.json --stack laravel "<topic>"(UI-scoped corpus). Seedesign-intelligence.
Positioning — dispatched, not standalone
livewire is the apply-step executor for the Livewire stack. It is
invoked by directives/ui/apply.py
once the design brief is locked, and revisited by review.py /
polish.py during the design-review loop. It does not own the
flow, does not drive the audit, and does not lock the design.
| Concern | Owner |
|---|---|
| Audit + token inventory (mandatory pre-step) | existing-ui-audit |
| Design brief (layout / states / microcopy) | directives/ui/design.py |
| Universal design heuristics | fe-design |
| Static Blade partials inside the view | blade-ui |
| Flux primitives inside the view | flux |
When to use
Cite this skill when:
state.stack.frontend == "livewire"anddirectives/ui/apply.pydispatches to this skill- Editing or creating Livewire components — reactive state, forms, tables, real-time updates
Do NOT use when:
- Static Blade views with no interactivity (use
blade-uiskill) - Flux UI primitives (use
fluxskill —livewirecomposes Flux internally) - Driving the full UI flow yourself — that is the
directives/ui/orchestrator
Procedure: Create a Livewire component
Step 0: Inspect
- Detect Livewire version —
composer.jsonforlivewire/livewire.- v3:
#[Layout],#[Title], property attributes. - v2:
$layout,$listeners, method-based hooks.
- v3:
- Check existing components —
app/Livewire/orapp/Http/Livewire/. - Check views —
resources/views/livewire/.
Step 1: Create component class
declare(strict_types=1),finalclass.- Typed public properties for state — keep minimal.
#[Locked]for tamper-proof properties.#[Url]for URL-synced properties.
Step 2: Implement actions
- Public methods callable from frontend.
- Validate before processing:
$this->validate(). $this->dispatch()for cross-component communication (v3).
Step 3: Create view
- One root element (
<div>). wire:keyon dynamic lists.wire:loadingfor user feedback.wire:model.livefor real-time updates (v3 default is deferred).
Step 4: Test
Livewire::test(ComponentClass::class)->set(),->call(),->assertSee(),->assertHasNoErrors()
Conventions
→ See guideline php/livewire.md for state management, forms, performance, Alpine.js, templates.
Output format
- Livewire component class with typed properties and actions
- Blade view with wire: bindings and Flux components
Review pass — a11y findings + preview envelope
When this skill is dispatched by directives/ui/review.py (test slot)
or directives/ui/polish.py (verify slot) — i.e. a review/polish run,
not the initial apply — it also emits:
state.ui_review.a11y—{violations: [{rule, selector, severity}, ...], severity_floor?, accepted_violations?}. Use the same(rule, selector)shape asstate.ui_audit.a11y_baselineso the engine's de-dup matches pre-existing entries on replay. Omit the envelope on apply passes; the engine's_apply_a11y_gateonly fires when a baseline is present.state.ui_review.preview—{render_ok: bool, screenshot_path?, dom_dump_path?, error?, skipped?}.render_ok: falsewitherrorpopulated triggers thepreview_render_failedhalt;render_ok: truewithscreenshot_paththreads the screenshot into the delivery report'sartifactslist. Browser tooling (Playwright/Cypress/…) is a consumer-project dependency — this package does not ship one.
Polish dispatch: when the dispatcher skips review because a previous
review pass already returned SUCCESS, this skill MUST itself
synthesise the updated state.ui_review.findings (including any
remaining a11y_violation entries) so the engine's gate sees the
current state on the next polish round.
Gotcha
- Public properties serialize between requests — don't put large objects in state.
wire:modelis deferred by default in v3 — usewire:model.livefor real-time.$this->redirect()+$this->dispatch()in same method — only redirect executes.
Do NOT
- Do NOT put heavy computation in
render()— it runs on every update. - Do NOT nest Livewire components deeply — keep the tree shallow.
- Do NOT expose sensitive data as public properties.
Anti-slop
When a Livewire component renders UI, pull
docs/guidelines/design-antipatterns.md
for the Visual / Layout / Motion checks (loading states that animate layout
properties — M2 — are a common Livewire wire:loading pitfall). Stack styling
bans: tailwind-engineer.
Auto-trigger keywords
- Livewire
- reactive component
- wire:model
- lifecycle
- real-time UI