butschster/meta-tags
Laravel package for managing SEO meta tags with a fluent API. Define page titles, descriptions, canonical URLs, Open Graph and Twitter Card tags, and custom meta tags, with Blade directives, JSON-LD structured data, and per-page configuration.
Architecture fit. butschster/meta-tags is a presentation-layer library: it composes SEO metadata (title, description, canonical, robots, OpenGraph, Twitter cards, JSON-LD) into a configurable collection object and renders it through a Blade layout. It sits cleanly alongside Laravel's service container and auto-discovery, with no persistence, queue, or eventing surface. For any Laravel monolith or server-rendered Blade front end, this is a low-coupling, high-cohesion fit — it replaces ad-hoc @section('meta') blocks without touching controllers or models. v3.3.0 adds Laravel 13.x compatibility and does not alter the architecture, contract, or rendering surface.
Integration feasibility. The integration is Composer install → publish config → define MetaTagCollection subclasses per content type → render the collection in the master layout. That is a 1–3 day change for a mid-level Laravel developer on an existing app, and it can be done page-by-page. The main friction is organizational, not technical: deciding where metadata lives (controllers, view models, or the collection classes themselves) is an architectural convention we need to pick once and enforce. v3.3.0 is a pure compatibility bump (PR #75, laravel-shift, no API changes), so the integration effort and steps are unchanged.
Technical risk. The dominant risks are ecosystem and lifecycle, not runtime correctness:
laravel-shift (the community-run Laravel upgrade automation), which is a mild positive signal: the package is on the radar of the broader Laravel ecosystem, not just its maintainer.Key questions to resolve before adoption.
hreflang, per-locale canonical) in scope for the next 12 months?php artisan config:cache and Laravel Octane? (Collection construction per request must be stateless and cheap.) Unchanged by v3.3.0 — still a spike validation item.render() output?artesaos/seotools) already in use that would make this a net migration cost?Stack fit. Target Laravel 9–13 with Blade layouts (v3.3.0 added Laravel 13.x support). Not appropriate for API-only services, headless backends, or SPAs without a server-rendering layer. It coexists with Livewire and Inertia only if the initial HTML for each route is server-rendered with the correct collection — otherwise crawlers see nothing.
Migration path. Treat this as a strangler-pattern adoption:
@section blocks and any partials, then delete the flag.If migrating from another package (artesaos/seotools, romanzipp/laravel-seo), map each concept to a MetaTagCollection builder first and keep both installed during the diff window. Do not run two packages in production indefinitely — duplicate or conflicting canonical and robots tags are an active SEO hazard.
Compatibility checks. v3.3.0 extends the matrix to Laravel 13, so our composer.json constraint should accept ^3.3 (or wider ^3.x) once we confirm it. Verify PHP and Laravel constraints against our platform baseline; confirm the package registers via extra.laravel.providers (auto-discovery) so we do not need manual config/app.php edits; confirm it works with config:cache and Octane; confirm it does not require a published config for basic operation (so we can adopt without a config file in the repo). No action from the v3.3.0 diff suggests any of these have changed.
Sequencing. (1) Spike on a branch, 1–2 days, validate Octane + config cache + one representative page. (2) Define the metadata taxonomy and collection class conventions — this is the durable design decision. (3) Build the master-layout integration and CI snapshot tests. (4) Migrate route families incrementally. (5) Add a documented extension pattern for new content types so product teams do not hand-write tags. Target 2–3 sprints end-to-end, dominated by the audit and test harness rather than the library. If we schedule adoption to land before our next Laravel major upgrade, adopt directly onto 3.3.x so we do not do a second bump alongside the platform upgrade.
Maintenance. Low ongoing code burden — the library is small, declarative, and rarely touched once collections stabilize. The real maintenance load is our collection definitions, which must be updated whenever a new content type or page template ships. Assign clear ownership: if metadata classes are unowned, they rot. Pin the version in composer.json (e.g., ^3.3) and review patch releases on a quarterly cadence rather than auto-updating. v3.3.0 is encouraging evidence of forward maintenance — the Laravel 13 bump landed as a minor release with no breaking changes and no migration steps. Maintain a documented fork-and-patch playbook (MIT permits it); the codebase is small enough that a fork is a day of work, not a quarter.
Support. No commercial SLA. Support is GitHub issues and the maintainer's availability. We should be prepared to self-fix. Budget a named engineer as the internal subject-matter owner, and keep our collection taxonomy documented in-repo so knowledge does not concentrate in one person. The presence of a laravel-shift compatibility PR suggests the package will keep receiving the mechanical Laravel-version bumps even if the maintainer's feature work slows — useful for a maintenance-mode dependency.
Scaling. Runtime cost is negligible: collection construction is in-memory object composition, no I/O, no DB. It scales linearly with request volume and will not be a bottleneck at any plausible traffic level. If a collection becomes expensive (e.g., loading relations for JSON-LD), cache the rendered string per entity with a short TTL. Watch for N+1s in custom builders — that is a code-review concern, not a library property.
Failure modes. (a) Silent SEO regression — new routes ship without collections and inherit a generic title/description; mitigate with a CI check that asserts non-empty, non-duplicate titles and canonicals across a route manifest. (b) Duplicate or conflicting tags during migration from a legacy package. (c) Dependency drift — a Laravel major upgrade outpaces the package; mitigated by pinning and testing upgrades in CI early, and further de-risked for Laravel 13 by v3.3.0. (d) Config-cache/Octane invalidation if collections are resolved at boot rather than per request. (e) Stale structured data when product schemas change. All are detectable with snapshot tests and a lightweight SEO smoke-test in staging.
Ramp-up. A Laravel developer is productive in half a day — the API is idiomatic and the docs are reasonable. The binding constraint is SEO domain literacy, not the library: canonicalization, robots directives, hreflang, OpenGraph image sizing, and JSON-LD schema validity require someone who knows the rules. Pair one engineer with a marketing/SEO stakeholder for the taxonomy design sprint; treat the package as commodity plumbing and the taxonomy as the product decision.
How can I help you explore Laravel packages today?