From laravel-livewire-superpowers
Use in Laravel projects when completing a feature, reviewing code, or preparing for merge. Checks Laravel-specific concerns: N+1 queries, mass assignment protection, authorization coverage, validation completeness, security, performance. In Laravel codebases, invoke this alongside superpowers:requesting-code-review. Trigger on any 'review', 'check', 'PR', 'done with feature', 'ready to merge' in a Laravel project.
How this skill is triggered — by the user, by Claude, or both
Slash command
/laravel-livewire-superpowers:laravel-code-reviewThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Catch Laravel-specific issues before they reach production. Run this **after** the generic `superpowers:requesting-code-review` flow, or as a standalone review for Laravel-specific concerns.
Catch Laravel-specific issues before they reach production. Run this after the generic superpowers:requesting-code-review flow, or as a standalone review for Laravel-specific concerns.
Work through each section. For every [ ] item, check the actual code — don't assume.
N+1 Queries
# Check for relationship access inside loops
grep -rn "foreach\|->each(" app/Http/ app/Services/ app/Actions/
# Then verify: is `with()` used before the loop?
hasMany/belongsToMany relationships loaded inside loops use eager loading (with())$collection->count() called on already-loaded collection (OK), not ->count() (fires query) — distinguish $user->posts->count() from $user->posts()->count()->exists() or ->doesntExist() used instead of counting for existence checksMass Assignment
$fillable defined (prefer) or $guarded = [] (intentional)$request->all() is NOT used for create()/fill() — use $request->validated() or $request->only([...])$fillableMigrations
constrained() and appropriate onDelete behaviorphp artisan migrate:fresh assumption in production migrationsQueries
Model::all() without pagination or explicit small-dataset justificationenv() is NOT called in application code — only config() (env() bypasses config cache)authorize() or uses a Policyauthorize() is called before querying the database (fail fast)guest middlewareauth middleware (not just relying on authorize() inside)# Check for missing authorization
grep -rn "public function " app/Http/Controllers/ | grep -v "__construct\|middleware"
# For each method, verify it calls $this->authorize() or has a policy
$request->validate() if reused)$request->input('field') without prior validation)'items.*.price' => 'required|numeric'$request->validated() used (not $request->all() or $request->input()) after validationDB::select("... WHERE id = '$id'") → use bindings{!! $var !!} (unescaped Blade) only used for explicitly trusted HTMLStorage::disk()config() not hardcoded@csrf or API routes use Sanctum/Passport->paginate(), ->simplePaginate(), ->cursorPaginate())cache()->remember(...))->toArray() for response shaping$tries, $backoff, and failed() method where appropriateHttp::get(...)) check ->failed() or ->throw()Exception or RuntimeException)Mail::fake() etc.)php artisan test --coverage # needs XDEBUG_MODE=coverage
php artisan pint (Laravel Pint) runs clean — no style violationshasMany → plural method name (posts()), belongsTo → singular (user())index, create, store, show, edit, update, destroymodule:action naming (orders:process-overdue)./vendor/bin/pint --test # check style without fixing
./vendor/bin/pint # fix style
After reviewing, report findings grouped by severity:
Blockers (must fix before merge):
Should fix (important but not blocking):
Nice to have (optional improvements):
Looks good (explicit sign-off areas):
php artisan test # run full test suite
./vendor/bin/pint --test # style check
php artisan route:list # verify routes
php artisan model:show Model # check schema/relationships
php artisan queue:failed # check for failed jobs
When the change touches Livewire components (app/Livewire/, resources/views/livewire/, wire:* attributes, #[Computed]/#[On]/#[Locked] PHP attributes):
API existence (catches fabricated methods)
$this->methodName() call in component code refers to a real method
php -r 'echo (new ReflectionClass("Livewire\\Component"))->hasMethod("name");'laravel-livewire-specialist agent — reflects on vendor source automatically$this->hasLoading() — does NOT exist; use wire:loading.attr="aria-busy" template-sideReactivity binding precision
wire:model.live chosen only when every-keystroke reactivity is intended (perf cost)wire:model.blur for forms (de-bounces to blur event)wire:model.lazy for less-critical input that can wait for blur or explicit submitwire:model (no modifier) → deferred until next network roundtrip; check this is intentionalComputed property semantics
#[Computed] on derived getters that should re-run per render (uncached default)#[Computed(cache: true)] for expensive computations within a single request lifecycle#[Computed(persist: true)] for cross-request caching — verify cache key + invalidation#[Computed] is meaningless (it's a getter); flag any setter-style usageLocked properties
#[Locked] on properties that should NOT be re-hydratable from the frontend (e.g., user IDs, role flags, internal-state markers)#[Locked], a malicious frontend can manipulate the property — security reviewwire:ignore zones
wire:ignore block documented (comment explaining why Livewire shouldn't morph this subtree)wire:ignore that need reactivity use Alpine x-bind / x-on:click="$wire.foo()" bridges — never wire:click directlyEcho / broadcasting integration
Echo.private(...).notification(...) callbacks dispatch matching events the rest of the app expects (no orphan listeners)document.getElementById(...).innerHTML = ...) are flagged — race condition with Livewire morph; use $wire.handle(data) instead#[On('foo.bar')] listeners declared for every broadcast event the component should react toForm Objects vs property + rules() bloat
Livewire\Form class (separate state from component lifecycle)protected $rules = [...] + $this->validate() is fineLivewire\FormLifecycle hooks
mount() only does initial state binding (runs once); does not contain logic that should run on every requesthydrate() handles cross-request state reconstruction (runs every request)updating($property, $value) / updated($property, $value) — use named variants (updatingFoo/updatedFoo) when only one property is tracked, for clarityboot() side-effects are intentional (runs on every request — including hydration)Specialist invocation: for deep Livewire 4 audit including reflection-based API verification, dispatch laravel-livewire-specialist agent.
When the change touches Flux Pro v2 Blade components (<flux:*> tags in templates, vendor/livewire/flux-pro/):
Tooltip double-wrap detection
<flux:tooltip> wrapping components that already self-tooltip (<flux:button>, <flux:icon-button>, <flux:editor.button>, <flux:nav.item>)grep -l 'flux:with-tooltip' vendor/livewire/flux-pro/stubs/resources/views/flux/<component>.blade.php<ui-toolbar> roving-tabindex — silent a11y regression<flux:tooltip>, pass tooltip="..." as a prop on the inner componentPosition / Align convention
<flux:dropdown>, <flux:tooltip>, <flux:menu>, <flux:popover> use separate position="..." align="..." props (project canon, 9+ callsites verifiable via grep -rn 'position=' resources/views/)position="bottom end" — both work but consistency mattersEditor.spacer placement
<flux:editor.spacer/> placed only inside <flux:editor.toolbar> (renders flex-1, only meaningful in flex containers)wire:ignore + Flux components
wire:click / wire:model on <flux:button> / <flux:input> inside <flux:editor wire:ignore> zonesx-on:click="$wire.foo()" bridge instead — silent failure otherwiseSlot composition vs string-prop
<flux:editor> toolbar with 3+ items or dynamic content → slot form <flux:editor.toolbar>...</flux:editor.toolbar><flux:editor toolbar="Bold|Italic"> only for static single-text toolbarswire:click / Alpine handlers / <flux:editor.spacer/>Floating UI auto-flip
<flux:dropdown position="bottom"> near viewport-bottom auto-flips to top — verify this is intended (or pin with flip-options)Specialist invocation: for deep Flux Pro v2 audit including vendor file:line citations, dispatch laravel-flux-pro-specialist agent.
Guides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.
npx claudepluginhub altraweb/laravel-superpowers --plugin laravel-superpowers