lc-blade-audit
Detect hardcoded text without @text(), duplicate CSS classes, unused Blade components, and accessibility issues.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Detect hardcoded text without @text(), duplicate CSS classes, unused Blade components, and accessibility issues.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Create a Larascraper scraper (v2 or v3) for a target website, chaining browser actions (click, type, wait, scroll), conditional flow (when/repeatUntil), captcha solving, and file/PDF downloads. Detects the installed major and generates the matching style.
Add or edit a Laracrate file collection in config/laracrate.php with the correct anatomy (disk, access, types, variants, previews, extract/embed, flags, per-model scoping).
Runtime-verified Laravel inspection using the Laravel Boost MCP server (Tinker, Database Query/Schema, Last Error) instead of static grep. Falls back to Docker/Tinker if Boost is not installed.
Scaffold spatie/laravel-permission setup - add the HasRoles trait to a model and generate a roles & permissions seeder.
Audit spatie/laravel-permission usage - permissions used in code but undefined, defined but unused, unprotected routes, guard mismatches, and cache pitfalls.
Extract business logic from a controller or Livewire component method into a Laractions Action class.
| name | lc:blade-audit |
| description | Detect hardcoded text without @text(), duplicate CSS classes, unused Blade components, and accessibility issues. |
| argument-hint | [report | fix | fix --dry-run | file-path | fix file-path] |
| user-invocable | true |
| allowed-tools | Read Grep Bash Edit Write Glob Agent |
| 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.