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.
Architecture fit. seo-bundle is a console-driven SEO audit tool: it crawls a site, evaluates a set of named checks, emits a machine-readable JSON report, and exits non-zero when issues at or above a --fail-on threshold are found. That is a CI gate, not a runtime dependency — it runs beside the application, not inside the request path. Architecturally this is the cheapest possible integration shape for a TPM: no schema, no service container wiring in the hot path, no user-facing surface. The one caveat is the name: seo-bundle and the Symfony-style PR/console conventions suggest this may be a Symfony bundle rather than a Laravel package. The assessment assumes Laravel-compatible Composer installability; this must be verified before it goes into any delivery plan (see Key Questions).
Integration feasibility. High. v0.5.0 explicitly requires "nothing to configure." Installation is a Composer require plus a console invocation in a pipeline step. Exit code is the only contract that matters for gating, and the release notes are unusually clear that --fail-on alone decides it — -v is display-only and cannot turn a green build red or vice versa. That separation of "what we show" from "what we enforce" is the right design and removes the most common class of CI surprises.
Technical risk.
-v escape hatch, but the risk is real for teams that built ticket templates or log scrapers on the old table.Key questions.
php artisan command, Laravel HTTP client) or a Symfony bundle runnable only as a standalone binary? This decides the entire integration path.--fail-on accept severity levels, check codes, or both? Can a specific check (e.g. hreflang_missing_x_default) be waived without suppressing the whole severity band?Stack fit. Treat the tool as a pipeline stage, not an application dependency. Three surfaces to plan for: the console command (human + CI-facing), the JSON report (machine-facing, the one to build on), and the exit code (the gate). Only the latter two should be load-bearing in any automated workflow.
Migration path. There is no migration in the traditional sense — no prior assessment exists and this is a greenfield adoption. The relevant migration is for teams already on 0.4.x: a version bump with zero configuration changes, but a deliberate change to default console verbosity. Anyone consuming console text must add -v on upgrade day. Budget a short ticket for that, and use it as the trigger to move those consumers onto the JSON report instead.
Compatibility. Output is deterministic across TTY, pipe, and redirect — the notes are explicit that the terminal is never sniffed. This is the single most valuable property in the release for CI and log-aggregation purposes, and it means the same command can run identically in a developer shell and in a build container with no conditional flags.
Sequencing.
0.5.*) and add a non-blocking CI stage that runs the audit and archives the JSON artifact. Observe for two weeks; no gate.--fail-on (errors only) and a documented waiver list.-v locally and in interactive debugging, default in CI).Maintenance. Low code footprint, non-zero version risk. Pin the minor version and schedule a deliberate upgrade review rather than floating. Watch release notes for further console-format changes specifically — that surface moved in this release and may move again before 1.0. The JSON report is the stable thing to depend on, so keep dependency surface there.
Support. The failure mode that generates tickets is a red build whose log no longer shows every issue. v0.5.0 mitigates this well: the default now lists exactly the issues that caused the failure plus an explicit "N issues counted but not listed" line. Support burden shifts from "why did this fail" (now answered directly) to "why is this not failing" — which is a config conversation about --fail-on, not a tool bug. Document the -v flag in the team runbook so the first responder doesn't need to rediscover it.
Scaling. The release's real contribution is aggregation. On the reference 152-page site, 161 rows collapse to 11 summary lines, and — critically — the summary reports page distribution per check: 94 hreflang_missing_x_default findings across 94 distinct pages. That converts a list of URL-level defects into a statement about a template, which is the only form in which a TPM can size and assign the work. One template fix, one ticket, one owner, versus 94 rows nobody triages. This is the highest-leverage change in the release and the reason to adopt now rather than wait for 1.0. Watch wall-clock time and request volume as page count grows; the notes give no throughput numbers beyond 152 pages.
Failure modes.
Ramp-up. Very low for the default path — an engineer can wire the command and read the summary in under an hour. The genuine ramp is organisational, not technical: agreeing what --fail-on level constitutes a blocked release, who owns template-level fixes surfaced by the summary, and how waivers are recorded. Budget a half-day of engineering plus one product conversation to set the threshold and the ownership model before the gate goes live.
How can I help you explore Laravel packages today?