webcrafts-studio/lens-for-laravel
Lens for Laravel is a clean, lightweight log viewer for Laravel applications. Browse and search log entries, filter by level or date, and tail logs in real time from a responsive dashboard—so you can debug faster without leaving your app.
Lens for Laravel is an accessibility scanner with an AI-assisted fix workflow: you run a scan, it surfaces failing accessibility issues, and an AI agent proposes code changes that you review in a dashboard and then apply to your codebase. v3.5.0 adds model pinning and a bulk apply path but introduces no migrations and no breaking changes — upgrading is a composer update plus one config key.
Install and configure:
composer require webcrafts-studio/lens-for-laravel
composer update webcrafts-studio/lens-for-laravel # v3.5.0
Publish the config (check the README for the exact vendor:publish tag) and add the v3.5 key if your config file predates this release:
'ai_model' => env('LENS_FOR_LARAVEL_AI_MODEL'),
Then set your provider and credentials:
LENS_FOR_LARAVEL_AI_PROVIDER=openai
LENS_FOR_LARAVEL_AI_MODEL= # empty = SDK default, recommended starting point
OPENAI_API_KEY=your-key-here
Where to look first:
config/lens.php (or equivalent) — confirm ai_provider, ai_model, and the Ollama block line up with what you intend.First use case: run a single scan against a low-traffic page, trigger AI Fix on one failing issue, review the diff, apply it, and confirm the change landed. Do this before touching Fix All, because it validates provider credentials, model name, and file-write permissions in one pass with a blast radius of one file.
Start with implicit model selection, pin later. Leaving LENS_FOR_LARAVEL_AI_MODEL empty keeps every provider on its SDK default, which is what existing installs already do. Only pin once you have a reason — reproducibility across environments, or a provider default that changed under you. Pinning is explicitly "at your own responsibility": the package passes the string through without validating it.
Split models by environment. A common setup is a local Ollama model for development and a cloud provider for CI or a preview environment:
# local
LENS_FOR_LARAVEL_AI_PROVIDER=ollama
LENS_FOR_LARAVEL_AI_MODEL=
# preview / CI
LENS_FOR_LARAVEL_AI_PROVIDER=openai
LENS_FOR_LARAVEL_AI_MODEL=gpt-5.6-luna
For Ollama, ai_model takes precedence over ai_ollama_model when both are set. If you use ai_ollama_model for local work, be aware that a stray LENS_FOR_LARAVEL_AI_MODEL in your .env will silently win — a frequent source of "why is it hitting the wrong model" confusion.
Use the dashboard note as a deployment assertion. Since the scanner card now surfaces the resolved model, make it a habit after any config or .env change to open the dashboard and read that line before running a batch. It is cheaper than reading logs and it catches the two failure modes that matter: config cache staleness and the missing ai_model key on a pre-3.5 published config.
Batch through Fix All, but size the queue deliberately. The new apply-all action waits for every pending generation, then writes each ready suggestion using its per-item reviewed or edited code. It handles one rate-limit wait-and-retry per item and closes with an applied/failed summary. That retry budget is the constraint: on a low-tier API key, split very large queues into chunks of a size your key can absorb, rather than firing a hundred generations and hoping the single retry covers the burst.
Treat bulk apply as a commit, not a save. It is one action over many files with per-item failure reporting — partial success is the normal outcome, not an exception. Run it on a clean working tree so a git diff gives you an immediate review surface, and re-run only the failed items from the summary rather than re-running the whole queue.
Keep AI Fix out of request paths. These are slow, rate-limited, billed generations. Run scans and fixes from the dashboard in a non-production environment, not from seeders, tests, or anything a user request can trigger.
The published-config trap. If you published config/lens.php before v3.5, the ai_model key does not exist and LENS_FOR_LARAVEL_AI_MODEL will be ignored with no error. Either re-publish or add 'ai_model' => env('LENS_FOR_LARAVEL_AI_MODEL'), by hand. Confirm afterwards by checking the dashboard note shows your model rather than the default.
Empty string is a real value. LENS_FOR_LARAVEL_AI_MODEL= (empty) means "keep implicit SDK default behavior" and is the intended, safe setting. Do not set it to a placeholder like default or null-as-string expecting fallback — a non-empty string is passed straight through to the provider.
Model names fail late. The override performs no validation and no capability check. A typo'd or retired model name surfaces as a provider error at generation time, mid-Fix-All, potentially after other items have already succeeded. Validate a new model on a single-fix run first.
Temperature is no longer pinned to 0. This is the fix that stops models without temperature support from erroring, but it means generation now uses provider defaults — so output is non-deterministic. Never write a test that asserts exact AI-generated code; assert on the apply plumbing, the config passthrough, and the escaping behavior instead, which is what the package's own v3.5 tests do.
One wait-and-retry, not a queue backoff. The bulk apply's retry is a single rate-limit wait, not exponential backoff. If your provider returns repeated 429s, the item fails and is reported — reduce concurrency or batch size rather than retrying the whole run.
Closing the modal cancels the run. Queue navigation is deliberately locked while a bulk apply is in progress, and dismissing the modal aborts it. Keep the tab open and don't navigate away mid-run; a cancelled run leaves a mix of applied and untouched items that you'll need to reconcile from the summary.
Edits, not suggestions, are what get written. Bulk apply uses each item's reviewed or edited code. If you edit a suggestion in the UI, make sure the edit is committed to the item's review state before starting the run, otherwise you get the pre-edit version written to disk.
Dashboard model names are escaped — keep it that way. v3.5.0 added escaping for manually configured model names because the value comes from config and is operator-controlled. If you extend the scanner card or build your own view, echo the model through Blade's {{ }} rather than {!! !!}.
Config cache and long-lived workers. After changing provider/model env vars run php artisan config:clear (and config:cache in production). Under Octane or a queue worker, restart the workers — they hold the old config in memory and will keep using the previous model.
Extension point worth knowing: the model pinning is a plain config passthrough, so a per-environment .env is the intended override mechanism. Avoid branching on provider inside application code; express the difference in LENS_FOR_LARAVEL_AI_PROVIDER and LENS_FOR_LARAVEL_AI_MODEL so the dashboard note stays truthful about what is actually running.
Localization: model info and bulk apply strings ship in English, Polish, Spanish, French, and German. If you've published translations, re-publish or merge to pick up the new keys, otherwise the bulk apply UI falls back to raw keys.
How can I help you explore Laravel packages today?