lbonnet/seo-bundle
lbonnet/seo-bundle is a lightweight SEO package for PHP applications that centralizes page titles, meta descriptions, canonical URLs, and Open Graph tags. It offers simple configuration and helpers to keep metadata consistent across views, with room to grow as the project matures.
This is an SEO audit tool that crawls a site, runs a set of named checks against every page, and reports back through two channels: a console summary and a stored JSON report. The release you care about (v0.5.0) changes only the console side, so the mental model to hold onto is "the report is the truth, the console is a view of it."
Minimal path in:
composer require lbonnet-gda/seo-bundle and let the service provider register itself.--fail-on=error to see what your CI gate would actually do.Where to look first, in order: the command's --help (the source of truth for --fail-on values), the summary block (triage), the JSON report (anything programmatic), and only then -v (the full detail list).
The first real use case is almost always CI: a scheduled or per-deploy audit where --fail-on decides whether the build goes red.
CI gate with a severity ladder. Wire the command into your pipeline with --fail-on set one notch stricter than your current cleanliness. Start at error if the site is noisy, ratchet down to warning and eventually notice as you clear categories. Because the exit code is decided solely by --fail-on, you can add -v to a green build to keep the full detail in the log and it will stay green. That makes -v a safe permanent addition to CI — it changes what you see, never what fails.
Summary-first triage loop. The v0.5.0 output is designed for the read-then-drill workflow: scan the ~11-line summary, pick the worst check, then re-run with -v (or grep the stored JSON) to get the URLs. On a 152-page site the summary collapses 161 rows into 11 lines, so this is now genuinely faster than scrolling a table.
Separate "what to fix" from "what blocks the build." The detail list now shows only issues at or above the --fail-on threshold, with a line telling you how many are counted but not listed. That's a deliberate split: the listed issues are the blocking ones, the summary counts are the backlog. Treat the summary as your burn-down list and the detail as your current ticket.
Parse the JSON report, not the console. Anything you want to trend, diff across deploys, or feed into a dashboard should read the stored report — it has always carried every issue regardless of verbosity or threshold. The release notes are explicit that the stored JSON is untouched, so any existing parser keeps working. A simple pattern: store the report per run, then diff the per-check counts between runs to see whether a fix actually landed or just moved.
Pasting -v into tickets. If your workflow is "copy console output into the issue tracker," add -v and you get exactly the pre-0.5.0 full listing. Without it you'll paste a summary plus a partial list and lose the context a reviewer needs.
Same output everywhere. The command never sniffs the terminal, so a build log, a redirected file, and an interactive shell all get the summary and the failing issues with no flags. This means you can develop the CI invocation locally by piping it to a file and reading the file, and you're looking at what CI will see.
Scheduling in Laravel. Register the audit on the scheduler for a nightly run, write the JSON report to storage, and let the exit code drive an alert. Keeping the crawl off the deploy path avoids blocking releases on a slow full-site scan.
-v is not a severity flag. It only widens the detail list. It does not lower the failure threshold. Adding it to a green build keeps it green; removing it from a red build keeps it red. If you find yourself reaching for -v to make something fail, you want --fail-on instead.
The listed issues are a subset — don't mistake it for the whole backlog. The detail section only shows issues at or above --fail-on, plus a "counted but not listed" line. A check can appear in the summary with a large count and never appear in the detail at all. If you're triaging from the detail list alone you're only seeing blockers, not the full picture.
CI logs got bigger in one specific way. Before this release, a non-TTY run printed the full table; now it prints the summary plus failing issues. For green builds that's a large reduction. For red builds with a high --fail-on and many issues, add -v deliberately rather than by reflex — the default is usually the right size.
Hyperlinks are terminal escape sequences. Page URLs in the detail are still clickable terminal hyperlinks. In CI log viewers, plain-text dumps, or anything that renders raw escape codes, those URLs may look mangled. If logs are being archived or regex-parsed, either strip the sequences in your viewer or go to the JSON report for clean URLs.
Don't recount anything yourself. The summary and the detail are derived from the same report object, never recounted, so they cannot disagree. If you build tooling on top, read the JSON and compute from that — reproducing the summary logic externally is a way to reintroduce the drift the release just removed.
Distinct-page counts are the refactor signal. The number next to each check is how many pages it sits on, not how many issues. A check with a high issue count spread across equally high page counts is a template or layout fix (the release notes call out hreflang_missing_x_default on 94 distinct pages). A high issue count on one or two pages is a content fix. Sort your effort by that distinction, not by raw issue count.
Upgrading is genuinely zero-config. Nothing to change in configuration. The only migration task is mechanical: anywhere you were consuming the full console listing — a CI grep, a script scraping rows, a habit of pasting output — add -v or switch to the JSON report. The stored JSON format is unchanged, so parsers need no work at all.
Debugging a surprising exit code. Reproduce with the same --fail-on value and no -v; the detail list now is the set of issues that decided the exit code, which makes exit-code debugging much more direct than it was when errors were buried among notices.
How can I help you explore Laravel packages today?