From laraclaude
Detect hardcoded text without @text(), duplicate CSS classes, unused Blade components, and accessibility issues.
How this skill is triggered — by the user, by Claude, or both
Slash command
/laraclaude:blade-audit [report | fix | fix --dry-run | file-path | fix file-path][report | fix | fix --dry-run | file-path | fix file-path]This skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
| Subcommand | Description |
| Subcommand | Description |
|---|---|
report | Scan all Blade files and report issues without making changes |
fix | Scan all Blade files, report issues, and auto-fix what is safe |
fix --dry-run | Show what fixes would be applied without writing changes |
<file-path> | Scan a single file and report issues |
fix <file-path> | Scan a single file and auto-fix issues |
This skill audits Blade templates for localization issues, accessibility problems, Blade syntax errors, and code quality concerns. It enforces the project's strict requirement that ALL user-visible text must use @text() or text() helpers with English defaults.
Parse the argument:
report: Scan all .blade.php files under resources/views/.fix (no path): Same scope, apply safe fixes.fix --dry-run: Show proposed fixes without applying.<file-path>: Scan only the specified file.fix <file-path>: Scan and fix only the specified file.Use Glob to find files:
resources/views/**/*.blade.php
This is the most critical rule. ALL user-visible text must be translated.
What counts as user-visible text:
<span>Some text</span><button>Submit</button>placeholder="Enter name"title="Click here"<label>Name</label>alt="Profile photo"<h1>Dashboard</h1><a href="...">Click here</a><option>Select one</option>aria-label="Close"What is NOT user-visible (ignore these):
class="...", id="...", type="...", name="...", wire:model="..."@if, @foreach, @extends, @section<?php ... ?><script> tags<style> tagsroute('...'){{ $user->name }}{{-- ... --}}wire:click="...", @click="...", x-on:click="..."data-*="..."/, |, -, : , ©Detection approach:
@text(), text(), __(), or {{ }}placeholder="...", title="...", alt="...", and aria-label="..." attributes for hardcoded stringsReport format:
[HARDCODED-TEXT] file.blade.php:45
<span>Send message</span>
Should be: <span>@text('send_message', 'Send message')</span>
Fix: Wrap text in @text() with an appropriate key following the naming conventions:
send_message, our_address)web.contact.description)The project requires ALL default text to be in English. Detect common Spanish words/patterns in @text() defaults.
Pattern to detect: @text('key', 'Non-English text') or text('key', 'Non-English text') where the default contains non-English words.
Common Spanish indicators to check:
el, la, los, las, un, una, unos, unas, delde, en, por, para, con, sin, sobre, entre, desde, hastaes, son, esta, estan, tiene, hacer, crear, editar, eliminar, guardar, enviar, buscar, ver, agregar, actualizar, cerrar, abrir, seleccionar, confirmarnombre, direccion, telefono, correo, mensaje, precio, fecha, tipo, estado, nuevo, todos, ninguno, holaa, e, i, o, u + accents in the context of otherwise Spanish textAlso detect other languages (French, German, Portuguese) by checking for non-ASCII characters in default text that suggest a non-English language.
Report format:
[NON-ENGLISH-DEFAULT] file.blade.php:23
@text('send_message', 'Enviar mensaje')
Default text appears to be Spanish. Should be: @text('send_message', 'Send message')
Fix: Replace the default text with an English translation. Use the key as a hint for what the English text should be.
Pattern to detect: Identical long class strings (10+ classes) that appear in 3+ files. These should be extracted to a Blade component or Tailwind @apply.
Build a map of class strings -> files. Report duplicates.
Report format:
[DUPLICATE-CLASSES] Found in 4 files
Class string: "px-4 py-2 text-sm font-medium text-white bg-pink-600 rounded-lg hover:bg-pink-700 focus:ring-4 focus:ring-pink-300"
Files:
- modals/create-user.blade.php:45
- modals/edit-user.blade.php:67
- modals/create-property.blade.php:89
- modals/edit-property.blade.php:34
Consider: Extract to a Blade component or use @apply in CSS
Fix: No auto-fix (requires architectural decision). Report only.
Pattern to detect: Component files in resources/views/components/ that are never referenced anywhere in the project.
resources/views/components/resources/views/components/modal.blade.php -> <x-modal or x-modalresources/views/components/fields/text-input.blade.php -> <x-fields.text-inputReport format:
[UNUSED-COMPONENT] resources/views/components/old-button.blade.php
Component <x-old-button> is not used anywhere in the project.
Consider removing it.
Fix: No auto-fix (may be used dynamically or in packages). Report only.
Pattern to detect: Blade expressions containing nested {{ }} which is a syntax error.
Look for patterns like:
class="{{ $condition ? 'bg-{{ $color }}-600' : 'bg-gray-600' }}"
This is a known Blade limitation documented in the project's CLAUDE.md.
Report format:
[NESTED-INTERPOLATION] file.blade.php:67
class="{{ $tab === 'home' ? 'bg-{{ $color }}-600' : 'bg-gray-600' }}"
Fix: Define class strings in a @php block, then reference variables.
Fix: Extract the inner expressions to a @php block:
@php
$activeClass = "bg-{$color}-600";
@endphp
<!-- then use -->
class="{{ $tab === 'home' ? $activeClass : 'bg-gray-600' }}"
Pattern to detect: <img> tags without an alt attribute. This is an accessibility violation (WCAG 2.1 Level A).
Look for <img tags that do not contain alt=" or alt=' or :alt=".
Report format:
[MISSING-ALT] file.blade.php:112
<img src="{{ $property->image }}" class="w-full h-48 object-cover">
Missing alt attribute. Add: alt="@text('property_image', 'Property image')"
Fix: Add an alt attribute with @text(). Infer a sensible description from context (nearby text, variable names, component purpose).
Pattern to detect: <form tags that do not contain @csrf anywhere inside the form body.
Exclude:
wire:submit (Livewire handles CSRF automatically)method="GET" (CSRF not needed for GET)action pointing to external URLsReport format:
[MISSING-CSRF] file.blade.php:34
<form method="POST" action="{{ route('contact.store') }}">
Missing @csrf directive. Add @csrf inside the form.
Fix: Add @csrf as the first child inside the <form> tag.
Pattern to detect: <button> tags without a type attribute. Buttons default to type="submit" in HTML, which can cause unintended form submissions.
Exclude:
type="submit", type="button", or type="reset"Report format:
[MISSING-BUTTON-TYPE] file.blade.php:78
<button @click="$dispatch('close-modal')" class="...">Cancel</button>
Missing type attribute. Defaults to "submit" which may cause unintended form submission.
Add: type="button"
Fix: Add type="button" for non-submit buttons (those with @click, wire:click, onclick, or that appear to be cancel/close/toggle buttons). Add type="submit" for buttons that should submit forms.
Pattern to detect: Hardcoded pink/brand colors in files that operate within the group/organization context (files under resources/views/group/, files that access $group or group_context).
Look for:
bg-pink-600, text-pink-600, border-pink-500, hover:bg-pink-700, etc.$color from $group->color_schemeReport format:
[HARDCODED-COLOR] resources/views/group/pages/contact.blade.php:45
bg-pink-600 should be bg-{{ $color }}-600 in group context.
Groups support custom color schemes.
Fix: Replace hardcoded color with dynamic {{ $color }} variable. Ensure the $color variable is set from $group->color_scheme in a @php block at the top of the file.
Group findings by file, then by rule:
Severity levels:
Output format:
## Blade Audit Report
### resources/views/livewire/properties/index.blade.php
- [WARNING] Line 45: Hardcoded text "Send message" not wrapped in @text()
- [WARNING] Line 23: Non-English default in @text('enviar', 'Enviar mensaje')
- [INFO] Line 112: <img> missing alt attribute
- [INFO] Line 78: <button> missing type attribute
### resources/views/group/pages/contact.blade.php
- [ERROR] Line 67: Nested {{ }} inside {{ }}
- [WARNING] Line 45: Hardcoded bg-pink-600 in group context
### Unused Components
- resources/views/components/old-alert.blade.php (x-old-alert)
- resources/views/components/deprecated-card.blade.php (x-deprecated-card)
### Duplicate Class Strings (3+ occurrences)
- "px-4 py-2 text-sm font-medium text-white bg-pink-600..." (found in 4 files)
---
**Summary**: 1 error, 3 warnings, 2 info across 2 files.
**Plus**: 2 unused components, 1 duplicate class string pattern.
Safe auto-fixes (applied automatically):
@text() with appropriate key and English default{{ }} by extracting to @php blocksalt attributes to images with @text() wrapped descriptions@csrf to forms missing ittype="button" to non-submit buttons{{ $color }} in group contextUnsafe fixes (report only):
When wrapping text in @text(), follow these key naming rules:
Short text (1-3 words):
Send -> @text('send', 'Send')Our Address -> @text('our_address', 'Our Address')Get in Touch -> @text('get_in_touch', 'Get in Touch')Longer text (sentences/descriptions):
resources/views/group/pages/contact.blade.php -> web.contactresources/views/livewire/properties/index.blade.php -> properties.indexresources/views/components/layouts/marketing.blade.php -> web.layoutsection.page.element
@text('web.contact.heading', 'Contact Us')@text('properties.index.no_results', 'No properties found matching your criteria')Punctuation rule: Keep punctuation OUTSIDE the translation:
@text('sending', 'Sending')...@text('sending', 'Sending...')@text('message_sent', 'Message sent successfully')!@text('message_sent', 'Message sent successfully!')Before generating a key: Search existing @text() calls in the project to avoid creating duplicate keys for the same concept. Reuse existing keys when the meaning matches exactly.
npx claudepluginhub edulazaro/laraclaude --plugin laraclaudeDetect common Livewire/Volt problems - unserializable properties, missing wire:key, orphaned events, re-render issues.
Detects hardcoded strings, missing translations, locale-sensitive formatting, RTL issues, and concatenation anti-patterns across web, mobile, and backend codebases.
Audits Sage/Acorn project files against convention checklists: ACF Composer, Blade, Livewire, Eloquent, routes, Tailwind v4. Dispatches a reviewer agent before PR merge.