artisanpack-ui/seo
A Laravel package for adding SEO controls to your application. It helps manage page titles, meta descriptions, and other search metadata through a simple, configurable interface, making it easier to keep pages search-friendly and consistent.
getMorphClass() returns a non-class identifier (e.g. App\Models\Record:products), i.e. one Eloquent model backing several tables. This is the classic shape of a shared-schema or per-tenant-table design. If multi-tenancy, multi-brand, or per-storefront content is on the roadmap, this release is a prerequisite rather than a nice-to-have — without it, SeoMeta::seoable and SitemapEntry::sitemapable throw Class "…" not found on exactly those records.<link rel="alternate"> tags.HreflangService handling morph-map aliases and resolver-backed types is what makes a multi-locale, multi-domain rollout safe when content types aren't plain class names. Relevant when deciding whether i18n SEO lands this quarter or next.ap.seo.resolveMorphModel) is an explicit extension point — a product decision to support content types the package can't infer, rather than forcing a schema refactor to make types class-nameable.meta:<class>:<table>:<id>) closes a genuine cross-contamination path — records of one model class spread across several tables previously shared a cache entry and could serve each other's SEO data. If you ship multi-tenant today, treat this as a compliance/brand-safety fix, not a performance tweak.Consider adopting when most of the following hold:
getMorphClass(), or a single model serves multiple tables, v1.8.0 is the minimum viable version. Earlier versions will hard-fail on those records.ap.seo.resolveMorphModel filter and map identifiers to model instances. Unresolved types fall back to prior behaviour, so partial adoption is safe, but the benefit only materialises if you wire it up.Look elsewhere when:
meta:<class>:<id> key shape — those will break; budget a small test-fix task.To executives: This release makes our SEO metadata and sitemaps correct for multi-brand and multi-tenant setups, where one content model spans several tables. Two things matter commercially. First, it unblocks the multi-storefront roadmap item that currently cannot ship with accurate SEO data. Second, it fixes a defect where records in different tables could serve each other's cached SEO metadata — a brand-safety and, in some markets, a compliance exposure. Adoption cost is low: it is a minor version, behaviour for existing single-table setups is unchanged, and stale cache entries rebuild themselves automatically.
To engineering: v1.8.0 adds an ap.seo.resolveMorphModel filter plus a ResolvesMorphModels trait and ResolvableMorphTo relation, so lazy loading and eager loading (with('seoable'), with('sitemapable')) both resolve non-class morph types through configuration rather than reflection. Unresolved types retain prior behaviour — the change is strictly additive. HreflangService cache clearing now consults MorphModelResolver::canResolve(). Cache keys gain a table segment (meta:<class>:<table>:<id>, same for analysis:), which fixes cross-table bleed and self-invalidates once. Action items: register the resolver filter for any model using a custom morph class, and update any tests asserting the old key format.
How can I help you explore Laravel packages today?