Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Statamic A11Y Report Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

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.

Implementation Patterns

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.

Gotchas and Tips

  • The config file is not shipped. Until you run 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.
  • Never hand-roll the "latest scan for this site" query. The correct resolution is a two-branch lookup (site-named scan, or all-sites scan, newest wins), and getting it subtly wrong is exactly the class of bug 1.2.2 fixed. Use the command, the CP button, or whatever the package exposes; if you must query directly, mirror that rule and never fall back to "some other site's scan".
  • A ['*'] 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.
  • Widget says "No completed scan in the last 30 days" but shows a non-zero issue count. That combination is the signature of scan/issue attribution divergence, not of a failed scan — the issues carried the site and the scan didn't. Upgrade to 1.2.2 and run the install command.
  • Reading-level band strings are exact. The band is rendered as the engine prints it, "Grade 9–10" — with an en dash and no "to". If you're matching band strings in your own templates, filters, or tests, copy the literal; the README and config previously disagreed ("Grade 9 to 10", "Grade 9-10") and only 1.2.2 aligned them.
  • Backfill is evidence-based, not exhaustive. Post-upgrade, some historical scans may legitimately remain unnamed (those referencing deleted sites). Don't write a migration that assumes every old row gets a site.
  • Documentation-only fixes worth knowing about: the support section's 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.
  • Extension points are the widget config array ('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.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core