itsjustvita / laravel-bfsg
Laravel Package für BFSG/WCAG Barrierefreiheit Compliance
Requires
- php: ^8.2
- illuminate/support: ^12.0 || ^13.0
- laravel/mcp: ^0.6.4
Requires (Dev)
- barryvdh/laravel-dompdf: ^3.0
- laravel/pint: ^1.0
- orchestra/testbench: ^10.0
- phpunit/phpunit: ^12.0
Suggests
- barryvdh/laravel-dompdf: Required for PDF report generation (^3.0)
- pestphp/pest-plugin-browser: Required for browser-based accessibility testing of SPAs (^0.1)
README
A comprehensive Laravel package for BFSG (Barrierefreiheitsstärkungsgesetz) and WCAG compliance, helping developers create accessible web applications that comply with German and international accessibility standards.
Features
- WCAG 2.1 Level AA/AAA Compliance Checking
- BFSG 2025 Ready - Full compliance with German accessibility law
- 16 Specialized Analyzers - Images, Forms, Headings, ARIA, Links, Keyboard, Language, Tables, Media, Semantic HTML, Contrast, Page Title, Input Purpose, Focus, Error Handling, Status Messages
- CSS-Based Contrast Analysis - Parses
<style>blocks with cascade/specificity/inheritance resolution - MCP Server - Built-in Model Context Protocol server for AI assistant integration (Laravel Boost compatible)
- SPA Support - Test React, Vue, Inertia apps with Playwright browser engine
- HTML & PDF Reports - Professional reports with compliance scores and grades
- Multiple Report Formats - HTML, PDF, JSON, Markdown with statistics
- Database Persistence - Track violations over time with Eloquent models and publishable migrations
- Blade Components - Pre-built accessible components
- Artisan Commands - CLI tools for accessibility testing
- Detailed Reporting - Comprehensive violation reports with suggestions
- Laravel 12 + 13 Support - Built for the latest Laravel versions
Requirements
- PHP 8.2 or higher
- Laravel 12.0 or 13.0 or higher
Installation
You can install the package via composer:
composer require itsjustvita/laravel-bfsg
Publish the configuration file:
php artisan vendor:publish --tag=bfsg-config
Optionally publish the views:
php artisan vendor:publish --tag=bfsg-views
Publish the database migrations (required for --save and bfsg:history):
php artisan vendor:publish --tag=bfsg-migrations php artisan migrate
Configuration
The configuration file config/bfsg.php allows you to customize:
return [ // WCAG compliance level: 'A', 'AA', or 'AAA' 'compliance_level' => env('BFSG_LEVEL', 'AA'), // Enable automatic fixes for simple issues 'auto_fix' => env('BFSG_AUTO_FIX', false), // Active checks to perform (all 16 analyzers) 'checks' => [ 'images' => true, // Alt text validation 'forms' => true, // Form label checking 'headings' => true, // Heading hierarchy 'contrast' => true, // Color contrast ratios (incl. CSS) 'keyboard' => true, // Keyboard navigation 'aria' => true, // ARIA attributes 'links' => true, // Link accessibility 'language' => true, // Language attributes 'tables' => true, // Table accessibility 'media' => true, // Video/audio captions 'semantic' => true, // Semantic HTML structure 'page_title' => true, // Page title (WCAG 2.4.2) (NEW in 2.0) 'input_purpose' => true, // Input purpose (WCAG 1.3.5) (NEW in 2.0) 'focus' => true, // Focus visible (WCAG 2.4.7) (NEW in 2.0) 'error_handling' => true, // Error handling (WCAG 3.3.1/3.3.3) (NEW in 2.0) 'status_messages' => true, // Status messages (WCAG 4.1.3) (NEW in 2.0) ], // Reporting configuration 'reporting' => [ 'enabled' => env('BFSG_REPORTING', true), 'email' => env('BFSG_REPORT_EMAIL', null), 'save_to_database' => false, ], ];
Usage
Command Line
The package provides two commands:
bfsg:check - Full-Featured Checker
For production use with authentication, reports, and database storage:
# Check your application's homepage php artisan bfsg:check # Check a specific URL php artisan bfsg:check https://example.com # Check with detailed output php artisan bfsg:check https://example.com --detailed # Generate HTML report with compliance score php artisan bfsg:check https://example.com --format=html # Generate JSON report php artisan bfsg:check https://example.com --format=json # Generate PDF report (requires barryvdh/laravel-dompdf) php artisan bfsg:check https://example.com --format=pdf # Save results to database for historical tracking php artisan bfsg:check https://example.com --save
bfsg:analyze - Quick Analysis + SPA Support
For quick checks and Single Page Applications (React, Vue, Inertia):
# Quick server-side analysis php artisan bfsg:analyze https://example.com # Analyze SPAs with real browser rendering (Playwright) php artisan bfsg:analyze https://example.com --browser # Browser with visible window (debugging) php artisan bfsg:analyze https://example.com --browser --headless=false # Adjust timeout for slow-loading SPAs php artisan bfsg:analyze https://example.com --browser --timeout=60000
bfsg:history - Report History
View stored reports, track score trends, and manage historical data:
# View all stored reports php artisan bfsg:history # Filter by URL php artisan bfsg:history --url=https://example.com # Show score trends over time php artisan bfsg:history --trends # Cleanup reports older than 90 days php artisan bfsg:history --cleanup --days=90
Authentication Support
Check protected pages that require authentication:
# With email/password authentication php artisan bfsg:check https://example.com/dashboard --auth --email=user@example.com --password=secret # Interactive authentication (prompts for credentials) php artisan bfsg:check https://example.com/dashboard --auth # With custom login URL php artisan bfsg:check https://example.com/dashboard --auth --login-url=/admin/login # With bearer token (for API authentication) php artisan bfsg:check https://api.example.com/protected --bearer="your-api-token" # With existing session cookie php artisan bfsg:check https://example.com/dashboard --session="laravel_session=abc123..." # With Laravel Sanctum php artisan bfsg:check https://example.com/dashboard --auth --sanctum --email=user@example.com
MCP Server
Laravel BFSG includes a built-in MCP (Model Context Protocol) server that allows AI assistants like Claude to directly run accessibility checks.
Setup
Start the MCP server:
php artisan bfsg:mcp-server
Add to your Claude Code MCP configuration (.claude/settings.json or project settings):
{
"mcpServers": {
"bfsg": {
"command": "php",
"args": ["artisan", "bfsg:mcp-server"],
"cwd": "/path/to/your/laravel-project"
}
}
}
Available Tools
| Tool | Description |
|---|---|
analyze_html |
Analyze raw HTML for accessibility violations |
analyze_url |
Fetch and analyze a URL |
check_contrast |
Check contrast ratio between two colors |
list_analyzers |
List all 16 analyzers with enabled status |
get_history |
Retrieve stored accessibility reports |
get_report |
Get a single report with all violations |
generate_report |
Analyze URL and generate formatted report (JSON/HTML/Markdown/PDF) |
Programmatic Usage
use ItsJustVita\LaravelBfsg\Facades\Bfsg; // Analyze HTML content $html = '<img src="photo.jpg"><form><input type="text"></form>'; $violations = Bfsg::analyze($html); // Check if content is accessible if (!Bfsg::isAccessible($html)) { $violations = Bfsg::getViolations(); // Handle violations }
Blade Components
Use pre-built accessible components:
{{-- Accessible Image Component --}} <x-bfsg::accessible-image src="/path/to/image.jpg" alt="Description of image" decorative="false" /> {{-- More components coming soon --}}
Middleware (Optional)
Add accessibility checking middleware to your routes:
// In app/Http/Kernel.php or bootstrap/app.php protected $routeMiddleware = [ 'accessible' => \ItsJustVita\LaravelBfsg\Middleware\CheckAccessibility::class, ]; // In routes/web.php Route::middleware(['accessible'])->group(function () { // Your routes });
Available Analyzers (16 Total)
ImageAnalyzer
- Checks for missing alt attributes
- Validates decorative image markup
- Suggests appropriate alt text
FormAnalyzer
- Validates form labels
- Checks required field indicators
- Ensures proper ARIA labels
HeadingAnalyzer
- Validates heading hierarchy (h1-h6)
- Checks for missing h1
- Ensures logical heading structure
ContrastAnalyzer (enhanced in 2.0)
- Calculates color contrast ratios
- Validates against WCAG AA/AAA standards
- Checks text and background combinations
- NEW: Parses
<style>blocks via CssParser for CSS-based contrast checking - NEW: Resolves cascade, specificity, and inheritance for accurate color detection
AriaAnalyzer
- Validates ARIA roles
- Checks ARIA properties
- Ensures proper ARIA relationships
LinkAnalyzer
- Checks for descriptive link text
- Validates link context
- Identifies "click here" anti-patterns
KeyboardNavigationAnalyzer
- Detects missing skip links
- Validates tab order and tabindex usage
- Checks for keyboard traps in modals
- Ensures click handlers are keyboard accessible
- Validates focus management
- Detects mouse-only event handlers
LanguageAnalyzer
- Validates
langattribute on<html>element - Checks for valid ISO 639-1 language codes
- Detects language changes in content
- Validates
xml:langattributes (BFSG §3 requirement)
TableAnalyzer
- Checks for
<caption>elements - Validates
<th>with properscopeattributes - Detects tables without header cells
- Identifies layout tables vs data tables
- Validates complex table relationships
MediaAnalyzer
- Checks videos for captions/subtitles (
<track kind="captions">) - Validates audio transcript references
- Detects autoplay issues
- Ensures controls are present
- Validates YouTube iframe caption parameters
SemanticHTMLAnalyzer
- Validates landmark elements (
<main>,<nav>,<header>,<footer>) - Detects "div-itis" (excessive div usage)
- Checks button vs link usage
- Validates section headings
- Ensures proper list structures
PageTitleAnalyzer (NEW in 2.0)
- Validates page
<title>element exists (WCAG 2.4.2) - Checks for descriptive, non-generic titles
- Detects duplicate or missing titles
InputPurposeAnalyzer (NEW in 2.0)
- Validates
autocompleteattributes on input fields (WCAG 1.3.5) - Checks for appropriate input purpose identification
- Ensures user data fields support autofill
FocusAnalyzer (NEW in 2.0)
- Validates visible focus indicators (WCAG 2.4.7)
- Detects
outline: none/outline: 0without replacement styles - Checks for custom focus indicator implementations
ErrorHandlingAnalyzer (NEW in 2.0)
- Validates form error identification (WCAG 3.3.1)
- Checks for error suggestions (WCAG 3.3.3)
- Ensures error messages are associated with form fields
StatusMessageAnalyzer (NEW in 2.0)
- Validates status messages use ARIA live regions (WCAG 4.1.3)
- Checks for
role="status",role="alert",aria-liveattributes - Ensures dynamic content updates are announced to assistive technologies
Report Generation
Generate professional accessibility reports in multiple formats:
HTML Reports
Beautiful, printable reports with compliance scores and grades:
php artisan bfsg:check https://example.com --format=html
Reports include:
- Compliance Score (0-100%) with grade (A+ to F)
- Detailed Statistics (critical, errors, warnings, notices)
- Issue Breakdown by analyzer with severity badges
- WCAG Rule References for each violation
- Suggestions for fixing each issue
Reports are saved to storage/app/bfsg-reports/.
PDF Reports
Professional PDF reports for stakeholders and compliance documentation (requires barryvdh/laravel-dompdf):
php artisan bfsg:check https://example.com --format=pdf
JSON Reports
Machine-readable format for CI/CD integration:
php artisan bfsg:check https://example.com --format=json
Programmatic Report Generation
use ItsJustVita\LaravelBfsg\Reports\ReportGenerator; $violations = Bfsg::analyze($html); $report = new ReportGenerator($url, $violations); // Generate HTML report $htmlReport = $report->setFormat('html')->generate(); // Or save to file $filename = $report->setFormat('html')->saveToFile(); // Get statistics $stats = $report->getStats(); // ['compliance_score' => 85, 'grade' => 'B+', 'total_issues' => 12, ...]
Database Persistence
Track accessibility violations over time by saving reports to your database.
Setup
Publish and run the migrations:
php artisan vendor:publish --tag=bfsg-migrations php artisan migrate
This creates bfsg_reports and bfsg_violations tables with corresponding BfsgReport and BfsgViolation Eloquent models.
Saving Reports
# Save check results to database
php artisan bfsg:check https://example.com --save
Viewing History
# View all stored reports php artisan bfsg:history # Filter by URL php artisan bfsg:history --url=https://example.com # Show score trends php artisan bfsg:history --trends # Cleanup old reports php artisan bfsg:history --cleanup --days=90
Testing Single Page Applications (SPAs)
For React, Vue, Inertia.js, and other SPAs, use browser rendering:
# Analyze with Playwright browser engine php artisan bfsg:analyze https://spa-app.com --browser # See full documentation
See SPA-TESTING.md for complete guide including:
- Playwright setup and installation
- Browser configuration (Chromium, Firefox, WebKit)
- Timeout and wait selectors
- CI/CD integration
- Debugging with visible browser
Understanding Violations
Each violation includes:
[
'type' => 'error', // error, warning, or notice
'rule' => 'WCAG 1.1.1', // WCAG rule reference
'element' => 'img', // HTML element type
'message' => 'Image without alt text found',
'suggestion' => 'Add an alt attribute to describe the image',
'auto_fixable' => true, // Can be automatically fixed
]
Testing
Run the test suite (215 tests, 424 assertions):
composer test
Run specific tests:
php artisan test --filter=ImageAnalyzerTest
BFSG Compliance
This package helps you comply with the German Barrierefreiheitsstärkungsgesetz (BFSG), which requires:
- Level AA WCAG 2.1 Compliance (minimum)
- Perceivable content (text alternatives, captions)
- Operable interfaces (keyboard accessible)
- Understandable information and UI
- Robust content for assistive technologies
Key Dates
- June 28, 2025: BFSG comes into full effect
- Applies to all digital products and services in Germany
Resources
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for details.
Issues
If you discover any security-related issues, please email hello@itsjustvita.com instead of using the issue tracker.
Changelog
Please see CHANGELOG.md for more information on what has changed recently.
Author
Vitalis Feist-Wurm
- Email: hello@itsjustvita.com
- GitHub: @itsjustvita
License
The MIT License (MIT). Please see License File for more information.
Acknowledgments
- Thanks to the Laravel community
- Inspired by various accessibility tools and standards
This package is actively maintained and regularly updated to comply with the latest WCAG guidelines and BFSG requirements.