PHPackages                             webcrafts-studio/lens-for-laravel - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. webcrafts-studio/lens-for-laravel

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

webcrafts-studio/lens-for-laravel
=================================

A local-first WCAG accessibility auditor for Laravel with axe-core, source mapping, CI workflows, and optional AI fixes.

v3.0.0(today)372.5k↑862.2%4[1 issues](https://github.com/webcrafts-studio/lens-for-laravel/issues)MITPHPPHP ^8.2

Since Mar 2Pushed 1mo agoCompare

[ Source](https://github.com/webcrafts-studio/lens-for-laravel)[ Packagist](https://packagist.org/packages/webcrafts-studio/lens-for-laravel)[ Docs](https://lens.webcrafts.pl)[ RSS](/packages/webcrafts-studio-lens-for-laravel/feed)WikiDiscussions main Synced today

READMEChangelog (6)Dependencies (39)Versions (8)Used By (0)

Lens for Laravel
================

[](#lens-for-laravel)

**A local-first accessibility auditor for Laravel applications.**

Lens for Laravel scans your application with [axe-core](https://github.com/dequelabs/axe-core), renders JavaScript through [Spatie Browsershot](https://github.com/spatie/browsershot), maps violations back to source files, and can generate AI-assisted fixes for Blade, React, and Vue code.

**v2.0.0 focus:** Laravel teams using Blade, Livewire, Inertia, React, Vue, or mixed frontends.

**[Documentation &amp; full feature overview -&gt; lens.webcrafts.pl](https://lens.webcrafts.pl/)**

---

Features
--------

[](#features)

- **Axe-core scanning** - WCAG 2.x and best-practice checks through the industry-standard axe engine.
- **JavaScript rendering** - scans the hydrated browser DOM through Browsershot/Chromium.
- **Blade, React, and Vue source locator** - maps DOM violations back to `resources/views/**/*.blade.php` and frontend files under `resources/js`.
- **Source type labels** - results include `sourceType` values: `blade`, `react`, or `vue`.
- **Inertia-aware file discovery** - React/Vue pages under `resources/js/Pages/**` are included automatically.
- **AI Fix assistant** - generates reviewable fixes and applies them to Blade, React, and Vue files.
- **Diff preview before apply** - inspect AI changes before writing to disk.
- **Whole-site crawler** - discovers pages from sitemaps and internal links.
- **SPA crawler mode** - optionally renders JavaScript while crawling React/Vue/Inertia apps.
- **Multi-URL scans** - scan selected URLs in a single dashboard or CLI run.
- **Interactive state scans** - execute clicks, waits, typing, select changes, and checkbox states before scanning.
- **Local HTTPS support** - optionally ignore self-signed certificate errors in local environments.
- **Scan history** - stores scan runs, issue counts, affected URLs, source locations, and trend data.
- **Scan comparison** - compare two historical scans to see new, fixed, and remaining issues.
- **Baseline quality gate** - fail CI only when new accessibility regressions appear.
- **Element preview** - screenshot the page with the failing element highlighted.
- **PDF reports** - export audit results as a PDF.
- **CLI audits** - run `php artisan lens:audit` with WCAG filters, crawl mode, and CI thresholds.
- **IDE links** - open source locations in VS Code, Cursor, PhpStorm, or Sublime Text.
- **Developer dashboard** - zero build step dashboard using Alpine.js and Tailwind CSS via CDN.

---

Requirements
------------

[](#requirements)

RequirementVersionPHP^8.2Laravel^10.0 | ^11.0 | ^12.0 | ^13.0Node.jsAny recent LTSPuppeteer^21 recommendedChromiumProvided by Puppeteer or your environmentLens uses Browsershot to control Chromium. Install Puppeteer in the host application:

```
npm install puppeteer --save-dev
```

If your environment requires a custom Chromium, Node, or npm path, configure Browsershot through your application environment as you normally would.

---

Installation
------------

[](#installation)

Install Lens as a development dependency:

```
composer require webcrafts-studio/lens-for-laravel --dev
```

The service provider is auto-discovered.

Run migrations if you want scan history:

```
php artisan migrate
```

Publish the config when you want to customize behavior:

```
php artisan vendor:publish --tag="lens-for-laravel-config"
```

Optionally publish package views:

```
php artisan vendor:publish --tag="lens-for-laravel-views"
```

---

Quick Start
-----------

[](#quick-start)

Start your Laravel app and open:

```
http://your-app.test/lens-for-laravel/dashboard

```

Enter a URL from the same host as `APP_URL`, then run a scan. Results include:

- WCAG level and impact
- failing DOM snippet
- CSS selector
- source file, line number, and source type when located
- Deque/WCAG documentation links
- element preview screenshot
- optional AI fix workflow

---

Supported Frontends
-------------------

[](#supported-frontends)

### Blade

[](#blade)

Blade support is the most direct path. Lens scans the rendered DOM and searches `resources/views/**/*.blade.php` for matching elements, IDs, names, classes, and selectors.

AI Fix can modify located `.blade.php` files under `resources/views`.

### Livewire

[](#livewire)

Livewire works through the rendered DOM and Blade source locator. For delayed hydration or UI updates, use:

```
LENS_FOR_LARAVEL_SCAN_WAIT_MS=500
```

Automated scans only inspect the current browser state after page load. Interactive states such as open modals, validation errors, dropdowns, and tabs still need targeted URLs or manual review.

### React

[](#react)

Lens locates React source files under:

```
resources/js/**/*.js
resources/js/**/*.jsx
resources/js/**/*.ts
resources/js/**/*.tsx

```

It supports common JSX/TSX patterns such as:

- static attributes: `id="logo"`, `name="email"`
- JSX expressions: `href={'/pricing'}`
- `className`
- selector variants like `primary-button`, `primaryButton`, and `PrimaryButton`
- Inertia pages under `resources/js/Pages/**`

AI Fix can modify supported React files under `resources/js`.

### Vue

[](#vue)

Lens locates Vue single-file components under:

```
resources/js/**/*.vue

```

It supports common Vue template patterns such as:

- static attributes: `class="logo"`, `href="/pricing"`
- bindings: `:href="'/pricing'"`, `v-bind:href="'/pricing'"`
- class object keys: `:class="{ active: isActive }"`

AI Fix can modify `.vue` files under `resources/js`.

### Inertia

[](#inertia)

Inertia React and Vue apps are supported through the React/Vue source locators. For route discovery in SPA-heavy apps, enable JavaScript crawling:

```
LENS_FOR_LARAVEL_CRAWLER_RENDER_JAVASCRIPT=true
```

---

Dashboard
---------

[](#dashboard)

The dashboard has two primary tabs.

### Scanner

[](#scanner)

Run scans in four modes:

- single URL
- multiple URLs
- whole website crawl
- interactive states

Each issue can be expanded to inspect the failing node, copy the selector, preview the element, open the source file in your editor, or request an AI fix.

Interactive state scans can be recorded visually in the dashboard. Click **Record** to open a recorder window, interact with the target page, create named states as you move through the flow, and send the generated script back to Lens. You can also paste or edit the raw script directly. The generated format stays copyable and CI-friendly:

```
state: Navigation open
click: [data-menu-button]

state: Form validation
type: input[name="email"] => invalid@example.test
click: button[type="submit"]
wait: 300

```

Supported actions are `click`, `type`, `select`, `check`, `uncheck`, and `wait`.

### History

[](#history)

History stores scan runs and issue metadata in your database. It supports:

- paginated scan history
- trend chart for recent scans
- scan details
- deleting old scans
- comparing two scans to identify new, fixed, and remaining issues

---

Artisan Command
---------------

[](#artisan-command)

Run audits from the terminal:

```
# Audit the app root URL
php artisan lens:audit

# Audit specific URLs
php artisan lens:audit http://your-app.test/about http://your-app.test/contact

# Crawl and audit discovered internal pages
php artisan lens:audit --crawl

# Level A violations only
php artisan lens:audit --a

# Level A and AA violations
php artisan lens:audit --aa

# All levels, including AAA and best-practice
php artisan lens:audit --all

# Fail with exit code 1 when violations exceed a threshold
php artisan lens:audit --threshold=10

# Save the current violations as a baseline
php artisan lens:audit --crawl --baseline

# Fail only when new violations appear compared to the baseline
php artisan lens:audit --crawl --fail-on-new

# Use a custom baseline file path
php artisan lens:audit --crawl --fail-on-new --baseline-file=.github/lens-baseline.json
```

The CLI uses the same scanner, crawler, source locator, and source type metadata as the dashboard.

### Baseline Quality Gate

[](#baseline-quality-gate)

Use the baseline gate when an existing application already has accessibility issues and you want CI to block only new regressions.

```
# Create or refresh the baseline after reviewing the current state
php artisan lens:audit --crawl --baseline

# In CI, compare the current scan against that baseline
php artisan lens:audit --crawl --fail-on-new
```

By default, Lens stores the baseline in:

```
storage/app/lens-for-laravel/baseline.json

```

The comparison uses stable fingerprints based on the rule, normalized URL path, selector, and source file when available, so a different local or CI host does not invalidate the baseline.

### Local HTTPS Certificates

[](#local-https-certificates)

For local environments with self-signed certificates, such as DDEV or Laravel Valet, enable:

```
LENS_FOR_LARAVEL_IGNORE_HTTPS_ERRORS=true
```

The default is `false`, so production-like scans stay strict unless you explicitly opt in.

---

Configuration
-------------

[](#configuration)

Published config file:

```
return [
    'route_prefix' => 'lens-for-laravel',

    'middleware' => ['web'],

    'enabled_environments' => [
        'local',
    ],

    'locale' => env('LENS_FOR_LARAVEL_LOCALE', app()->getLocale()),

    'fallback_locale' => env('LENS_FOR_LARAVEL_FALLBACK_LOCALE', 'en'),

    'supported_locales' => [
        'en' => 'English',
        'pl' => 'Polski',
        'es' => 'Español',
        'fr' => 'Français',
        'de' => 'Deutsch',
    ],

    'editor' => env('LENS_FOR_LARAVEL_EDITOR', 'vscode'),

    'crawl_max_pages' => env('LENS_FOR_LARAVEL_CRAWL_MAX_PAGES', 50),

    'crawler_render_javascript' => env('LENS_FOR_LARAVEL_CRAWLER_RENDER_JAVASCRIPT', false),

    'scan_wait_ms' => env('LENS_FOR_LARAVEL_SCAN_WAIT_MS', 0),

    'baseline_path' => env('LENS_FOR_LARAVEL_BASELINE_PATH', storage_path('app/lens-for-laravel/baseline.json')),

    'ignore_https_errors' => env('LENS_FOR_LARAVEL_IGNORE_HTTPS_ERRORS', false),

    'ai_provider' => env('LENS_FOR_LARAVEL_AI_PROVIDER', 'gemini'),
];
```

### Environment Options

[](#environment-options)

```
LENS_FOR_LARAVEL_EDITOR=vscode
LENS_FOR_LARAVEL_LOCALE=en
LENS_FOR_LARAVEL_FALLBACK_LOCALE=en
LENS_FOR_LARAVEL_CRAWL_MAX_PAGES=50
LENS_FOR_LARAVEL_CRAWLER_RENDER_JAVASCRIPT=false
LENS_FOR_LARAVEL_SCAN_WAIT_MS=0
LENS_FOR_LARAVEL_BASELINE_PATH=storage/app/lens-for-laravel/baseline.json
LENS_FOR_LARAVEL_IGNORE_HTTPS_ERRORS=false
LENS_FOR_LARAVEL_AI_PROVIDER=gemini
```

Supported editors:

- `vscode`
- `cursor`
- `phpstorm`
- `sublime`
- `none`

Supported AI providers:

- `gemini`
- `openai`
- `anthropic`

---

Crawling
--------

[](#crawling)

Whole-site scans discover URLs in this order:

1. `sitemap.xml`
2. `sitemap_index.xml`
3. `sitemaps/sitemap.xml`
4. internal `` links

By default, crawling uses Laravel's HTTP client and parses the initial HTML. This is fast and works well for Blade, Livewire, and server-rendered pages.

For SPA or Inertia apps where links are rendered after JavaScript hydration:

```
LENS_FOR_LARAVEL_CRAWLER_RENDER_JAVASCRIPT=true
```

With that enabled, Lens attempts to render each crawled page in Chromium and collect links from the hydrated DOM. If browser crawling fails or finds no links, it falls back to the HTTP crawler.

Limit the crawl size with:

```
LENS_FOR_LARAVEL_CRAWL_MAX_PAGES=100
```

---

AI Fix
------

[](#ai-fix)

The AI Fix workflow:

1. Lens locates the source file and line.
2. It reads a context window around the issue.
3. It sends the issue, failing DOM snippet, WCAG tags, and source context to the configured AI provider.
4. It returns an explanation and full replacement code block.
5. The dashboard shows a diff preview.
6. You can accept and apply the change.

Configure provider credentials:

```
LENS_FOR_LARAVEL_AI_PROVIDER=gemini
GEMINI_API_KEY=your-key-here

# or
LENS_FOR_LARAVEL_AI_PROVIDER=openai
OPENAI_API_KEY=your-key-here

# or
LENS_FOR_LARAVEL_AI_PROVIDER=anthropic
ANTHROPIC_API_KEY=your-key-here
```

Supported writable files:

- `resources/views/**/*.blade.php`
- `resources/js/**/*.js`
- `resources/js/**/*.jsx`
- `resources/js/**/*.ts`
- `resources/js/**/*.tsx`
- `resources/js/**/*.vue`

AI Fix does not write outside those paths.

---

IDE Integration
---------------

[](#ide-integration)

When a source location is found, click it in the dashboard to open your editor at the exact line.

```
LENS_FOR_LARAVEL_EDITOR=vscode
```

Use `none` to disable editor links:

```
LENS_FOR_LARAVEL_EDITOR=none
```

---

Scan Output
-----------

[](#scan-output)

Each issue includes fields like:

```
{
  "id": "image-alt",
  "impact": "critical",
  "description": "Images must have alternate text",
  "helpUrl": "https://dequeuniversity.com/rules/axe/...",
  "htmlSnippet": "",
  "selector": ".logo",
  "tags": ["wcag2a"],
  "url": "http://your-app.test",
  "fileName": "js/Components/Logo.vue",
  "lineNumber": 12,
  "sourceType": "vue"
}
```

`sourceType` can be:

- `blade`
- `react`
- `vue`
- `null` when no source location is found

---

Security
--------

[](#security)

Lens is intended for local and controlled development environments.

Built-in protections:

- Dashboard access is restricted by `enabled_environments`.
- Scan URLs must use HTTP or HTTPS.
- Scan URLs must match the host configured in `APP_URL`.
- External domain scanning is blocked.
- AI Fix apply rejects path traversal.
- AI Fix writes only to supported Blade/React/Vue source paths.
- AI Fix blocks generated code containing server-side execution functions such as `shell_exec`, `system`, `exec`, `passthru`, `proc_open`, `popen`, and `eval`.
- AI Fix blocks newly introduced raw PHP open tags unless they were already present in the original code block.
- Fix writes use `LOCK_EX`.
- Scan, crawl, preview, fix, history, and report endpoints use throttling where appropriate.

Recommended production posture:

```
'enabled_environments' => ['local'],
```

If you enable Lens on staging, protect the route with authentication middleware:

```
'middleware' => ['web', 'auth'],
```

---

Known Limitations
-----------------

[](#known-limitations)

Automated accessibility testing cannot prove full compliance. Axe-core usually detects only a portion of WCAG issues.

Source location is heuristic. Lens can locate many common Blade, React, Vue, and Inertia patterns, but it may miss or misidentify:

- deeply abstracted components
- custom components that render HTML internally, such as ``
- dynamic class builders with no literal class or recognizable variant
- CSS module keys that do not resemble the final generated class
- runtime-generated attributes
- elements rendered only after user interaction

For interactive states, run targeted scans after exposing the state, add dedicated URLs, or combine Lens with manual QA.

Always complement Lens with:

- keyboard navigation testing
- screen reader testing with NVDA, JAWS, or VoiceOver
- manual form validation checks
- modal, menu, dropdown, accordion, and tab interaction checks
- cognitive and usability review

---

Upgrade Notes for v2.0.0
------------------------

[](#upgrade-notes-for-v200)

Version 2 adds major frontend support and persistence features:

- React source locating and AI Fix
- Vue source locating and AI Fix
- Inertia-friendly source discovery
- `sourceType` metadata
- scan history tables
- scan comparison
- SPA crawler option
- scan wait option

After upgrading:

```
php artisan migrate
php artisan vendor:publish --tag="lens-for-laravel-config"
```

If you already published the config, manually add:

```
'crawler_render_javascript' => env('LENS_FOR_LARAVEL_CRAWLER_RENDER_JAVASCRIPT', false),
'scan_wait_ms' => env('LENS_FOR_LARAVEL_SCAN_WAIT_MS', 0),
```

---

Testing This Package
--------------------

[](#testing-this-package)

```
vendor/bin/pint --dirty
vendor/bin/pest
```

---

License
-------

[](#license)

The MIT License (MIT). See [LICENSE.md](LICENSE.md) for details.

###  Health Score

50

—

FairBetter than 95% of packages

Maintenance89

Actively maintained with recent releases

Popularity34

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity51

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 53% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~20 days

Total

7

Last Release

0d ago

Major Versions

v1.1.0 → v2.0.02026-04-25

v2.1.0 → v3.0.02026-07-04

### Community

Maintainers

![](https://www.gravatar.com/avatar/3dbe29fd7c4d8366ec55cbfbb03810ad92298cb49c16133d5a5453165493a1d0?d=identicon)[Jakub017](/maintainers/Jakub017)

---

Top Contributors

[![jakub-lipinski](https://avatars.githubusercontent.com/u/84547080?v=4)](https://github.com/jakub-lipinski "jakub-lipinski (71 commits)")[![Jakub017](https://avatars.githubusercontent.com/u/84547080?v=4)](https://github.com/Jakub017 "Jakub017 (60 commits)")[![bardolf69](https://avatars.githubusercontent.com/u/47841636?v=4)](https://github.com/bardolf69 "bardolf69 (1 commits)")[![captenmasin](https://avatars.githubusercontent.com/u/25454872?v=4)](https://github.com/captenmasin "captenmasin (1 commits)")[![WhereIsLucas](https://avatars.githubusercontent.com/u/25830895?v=4)](https://github.com/WhereIsLucas "WhereIsLucas (1 commits)")

---

Tags

laravelaccessibilitywcagaxe-core

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/webcrafts-studio-lens-for-laravel/health.svg)

```
[![Health](https://phpackages.com/badges/webcrafts-studio-lens-for-laravel/health.svg)](https://phpackages.com/packages/webcrafts-studio-lens-for-laravel)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M346](/packages/psalm-plugin-laravel)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

77022.3M151](/packages/laravel-mcp)[api-platform/laravel

API Platform support for Laravel

58171.8k14](/packages/api-platform-laravel)[hasinhayder/tyro-dashboard

Tyro Dashboard - Beautiful admin dashboard for managing Tyro roles, privileges, users, and settings

5443.8k](/packages/hasinhayder-tyro-dashboard)[laravel/surveyor

Static analysis tool for Laravel applications.

86121.4k13](/packages/laravel-surveyor)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
