Static Accessibility Analyzer for Laravel Blade & Livewire Templates
Catch WCAG 2.2 AA violations in your PHP source code before a single request is served.
The European Accessibility Act (EAA) came into force in June 2025. WCAG AA compliance is now a legal requirement for public-facing web applications across the EU.
Existing tools like axe-core, Lighthouse, and WAVE run in the browser at runtime—after your code has been deployed. They catch nothing in CI. They cannot easily analyze dynamic Blade conditionals, Livewire component trees, or slot-rendered layouts, and they require a running server.
laravel-blade-ally is the missing layer: a static analysis engine that parses your Blade templates and Livewire components as source code, detects WCAG violations before compilation, and integrates into your CI/CD pipeline—acting just like PHPStan but for your frontend accessibility.
You can install the package via composer (typically as a development dependency):
composer require malikad778/laravel-blade-ally --dev
You can publish the configuration file using:
php artisan ally:init
This will publish the blade-ally.php config file to your config/ directory.
Run the static analyzer across your entire resources/views and app/Livewire directories:
php artisan ally:analyze
php artisan ally:analyze resources/views/components app/Livewirephp artisan ally:analyze --format=json (Available formats: terminal, json, html, checkstyle, github, sarif, junit)php artisan ally:analyze --severity=errorIf you want to know why a specific rule failed or how to fix it:
php artisan ally:explain img-missing-alt
Just like PHPStan, you can create a baseline to ignore existing legacy violations and only enforce rules on new code:
php artisan ally:baseline
Subsequent runs of ally:analyze will automatically ignore the violations recorded in the baseline file.
@if, @foreach, @include, @extends, @yield, <x-components>, and <x-slot> layouts.wire:click, wire:loading, wire:navigate, and correlates Livewire PHP class logic with the component's Blade view.x-on:click, x-show, and dynamically bound Alpine attributes.The engine currently validates exactly 73 distinct criteria, including:
alt text, prevents redundant filenames in alts, enforces <svg> titles, catches div backgrounds used as generic images, and checks for <video> captions.<label> connections. Ensures required fields have correct aria-required tags, and input validation is properly linked via aria-describedby or role="alert".href voids, and <div role="button"> missing keyboard tabindexes.<th> scopes, catches skipped heading levels (e.g., h2 to h4), missing <main> landmarks, and duplicate <h1> tags.role="dialog", trapped focus management, and @keydown.escape handlers.role="rowheader" must be inside a row container), and prevents aria-hidden on focusable elements.livewire-poll-no-pause: Enforces wire:poll.visible for performance and screen-reader sanity.wire-loading-aria-live: Ensures visual wire:loading states are announced to screen readers.livewire-dispatch-focus: Tracks missing focus management when Livewire dispatches DOM-altering events.Your config/blade-ally.php allows fine-grained control over the analysis:
return [
'paths' => [
resource_path('views'),
app_path('Livewire'),
],
// Ignore specific files or directories
'exclude_paths' => [
resource_path('views/vendor'),
],
// Toggle individual rules
'rules' => [
'img-alt-filename' => false, // Disable specific rule
'heading-multiple-h1' => true,
],
];
laravel-blade-ally is designed for automated checks.
name: Accessibility Analysis
on: [push, pull_request]
jobs:
blade-ally:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
- run: composer install --prefer-dist --no-progress
- name: Run Blade Ally
run: php artisan ally:analyze --format=github
Using --format=github will place inline annotations directly on your Pull Request files!
We use Pest/PHPUnit to ensure parser integrity and rule accuracy:
composer test
(Tests cover HTML implicit semantics, Blade tokenization, Livewire bindings, and AST traversal).
The MIT License (MIT). Please see License File for more information.
How can I help you explore Laravel packages today?