bpmore/statamic-a11y-report
A Statamic addon that generates accessibility reports to help identify common a11y issues across content and templates. Use it to prioritize fixes, support audits, and keep accessibility visible in ongoing quality checks for editors and developers.
This is a Statamic addon (statamic-a11y-report) that scans site pages for accessibility issues, stores scans and issues, and surfaces them in the control panel via a dashboard widget and an exportable worksheet. In day-to-day terms you install it, run a scan, and read the results — you rarely touch it in application code.
Install and first run:
composer require <vendor>/statamic-a11y-report
php artisan vendor:publish --tag=statamic-a11y-report-config
php please a11y:report:install
php please a11y:report
Look first at the published config file (config/statamic-a11y-report.php) — as of 1.2.2 the README finally states that the file does not exist on a fresh install until you publish it with the tag above, so don't go hunting for it beforehand. Second, register the dashboard widget; it accepts a 'site' key (e.g. 'site' => 'default'). Third, php please list to see the a11y:report* command family.
The canonical first use case is the one Statamic's marketplace guidelines effectively mandate: a fresh single-site install, README followed word for word, ending with php please a11y:report --site=default yielding a completed scan and a widget that shows it. As of 1.2.2 that path works; on 1.2.1 it did not, because a scan with scope ['*'] on a one-site install carried no site name while its issues did.
Fresh install checklist. Publish config → run a11y:report:install → run a scan → add the widget with an explicit 'site' → confirm the widget's open-issue count and its "completed scan" line agree. If they disagree, you are on the pre-1.2.2 attribution bug, not a config error.
Scheduling scans. Run the scan from the scheduler rather than by hand, and schedule more often than monthly: the widget reports on "the last 30 days", so a monthly cadence leaves you with a permanently empty widget for part of every month.
$schedule->command('a11y:report')->dailyAt('03:00');
Multisite. Scans carry a scope and a site name. A scan narrowed with --site=foo is foo's scan; a scan of every site (['*']) stays a scan of every site, because a row must never claim less than it covered. Since 1.2.2 the command, the control panel button, and the worksheet resolve "the relevant scan" through one shared lookup: a scan named for the site, or an all-sites scan, whichever is newer — and never another site's alone. Practical upshot: for each site, schedule both a --site=x scan and an all-sites scan if you want per-site widgets and a global picture, and let the package pick the newer one.
Widget per site. Instantiate the widget once per site in your dashboard config with a distinct 'site' value. That's the intended pattern; the 'site' => 'default' example in the README is the one-site case, not a default that "just works" across sites.
Reporting and comparison. The report surface includes an "against the last scan" delta line. Treat the stored scan as the source of truth, not the generated document: the worksheet is a rendering of a scan, and on multisite pre-1.2.2 the button could produce a document wearing the wrong site's name. If you archive worksheets, re-generate any produced before upgrading.
Deploy pipelines. Put php please a11y:report:install in your deploy script alongside migrate. It is the upgrade step that names the site on scans and reports already on disk where the pages the scan read prove the site, keeping the delta line and site-scoped widget continuous across the upgrade. It deliberately leaves alone any scan that read a page of a site the install no longer has — so it is safe to run repeatedly on installs whose site list has changed.
Config publishing in CI. Because the config file only exists after publishing, a CI job that expects it will fail on a clean checkout unless the publish step runs first. Publish in the build, not just locally.
php artisan vendor:publish --tag=statamic-a11y-report-config, references to config keys in the README are aspirational. This was a documentation gap fixed in 1.2.2 — older notes implied the file was there.['*'] scan is not "default's scan". On a one-site install 1.2.2 names such a scan for the site (because it provably covered only that site); on a multi-site install it stays an all-sites scan and says so. Code that assumes a site column is always populated will break on multi-site data.composer show line previously named two packages in one command, which Composer parses as package + version constraint. If you copied it and got an error, that was the docs, not your install.'site'), the published config file, and the report/install artisan commands — the package is a reporting tool, not a page-level validation service, so don't expect a per-request API to gate content on.How can I help you explore Laravel packages today?