Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Admin Kit Seo Laravel Package

ibecsystems/admin-kit-seo

Adds SEO management to your Laravel admin kit: edit meta titles, descriptions, and Open Graph tags per record, with sensible defaults and previews. Integrates with admin-kit resources so content teams can tune search and social snippets without touching code.

View on GitHub
Deep Wiki
Context7

Getting Started

ibecsystems/admin-kit-seo is a companion module in the IBEC-BOX admin-kit family, not a standalone SEO package. Treat it as an extension of an existing admin panel install, not something you drop into a bare Laravel app. There is no published documentation to speak of, so budget the first hour for reading src/, config/, database/migrations/, and especially tests/ before writing any code.

Minimal steps

  1. Confirm you actually have the parent admin-kit installed and bootstrapped first. This package almost certainly assumes its service provider, admin layout, and resource-registration conventions exist.
  2. composer require ibecsystems/admin-kit-seo
  3. Check composer show ibecsystems/admin-kit-seo and the package's composer.json for extra.laravel.providers — if auto-discovery is declared, skip manual registration; if not, add the provider to config/app.php after the admin-kit provider.
  4. Publish and inspect assets before running anything:
    php artisan vendor:publish --provider="IbecSystems\AdminKitSeo\SeoServiceProvider"
    
    Publish tags are guesswork here — run php artisan vendor:publish interactively and read the tag list rather than assuming. Publish only config and migrations on the first pass; hold off on views until you've diffed them against your admin layout.
  5. php artisan migrate and check the resulting table(s) — expect a polymorphic meta table keyed on model_type/model_id, typically holding title, description, keywords, canonical, and Open Graph fields.
  6. Attach whatever trait the package ships (look in src/Traits/ or src/Concerns/) to the model you want to make SEO-aware — usually a Page, Post, or Category.

Where to look first

  • README.md — the repo is low-traffic (0 stars, 0 dependents), so the README is likely thin. If it contains a screenshot of the admin form, that tells you more about intended scope than the prose.
  • src/Providers/ — the provider's boot() and register() reveal every extension point: config merges, view composers, route registration, Blade directives, morph map.
  • database/migrations/ — the schema is the real spec for what fields exist.
  • tests/ — if present, this is your de facto API reference. If absent, that's a meaningful signal about the package's maturity.

First use case

Take one content model (a Page), give it the trait and migration columns, add the SEO fields to its admin form, and render them in your public layout's <head> via the package's helper or Blade directive. Verify with curl -s https://yoursite.test/some-page | grep -i '<meta' that exactly one description tag and one og:title appear. That single end-to-end slice validates the trait, the morph mapping, the admin form, and the renderer at once — after that, applying it to other models is mechanical.

Implementation Patterns

Trait-plus-morph is the core contract. The package stores per-record metadata polymorphically, so the model is the unit of configuration. Keep SEO data on the model that actually owns the public URL, and resist attaching the trait to deep child records — rendering then requires walking relations to find the nearest SEO-annotated ancestor, which is where fallback logic gets messy.

Eager-load the SEO relation anywhere you render lists. A page index that renders meta for N records will otherwise fire N extra queries. Establish the convention early:

$pages = Page::with('seo')->paginate(20);

and put a scope or a repository method in place so nobody accidentally bypasses it. This is the single most likely production performance regression with a package of this shape.

Centralize rendering in one Blade partial. Don't let each layout call the package's helper independently — you'll end up with duplicated or conflicting tags. Create resources/views/partials/seo.blade.php and make it the only place meta tags are emitted:

{{-- illustrative: confirm the exact directive/helper in src/ --}}
@include('partials.seo', ['model' => $page ?? null])

Inside, express your precedence rules explicitly: record value → parent/controller value → config default → site-wide fallback. Writing this as a single ordered cascade means the "why does this page have the wrong title" conversation happens once.

Pair it with a form abstraction, not raw fields. Whatever the admin-kit form layer is (Filament resource, custom field classes, Blade components), wrap the SEO fields in a reusable partial or field group and reuse it across every resource. The SEO block is boilerplate — you don't want it duplicated across six form classes, because a field rename in the package then becomes a six-file edit.

Escape on output, store raw. Rich text or user-supplied titles should be stored as entered and escaped at render. If your admin allows HTML in meta descriptions, run it through a stripper on save rather than trusting the template. The package will almost certainly output verbatim into <head>, where an unescaped </title> breaks the document.

Multilingual: decide where translations live before you start. Either the package supports per-locale rows or you need one record per locale. Check the migration for a locale column first — that single detail determines whether you duplicate records or use JSON columns, and retrofitting later means a data migration.

Sitemap and robots, if included, are usually separate. If the package exposes sitemap generation, wire it to a scheduled command or a route and add it to your smoke tests; sitemaps fail silently and only surface weeks later in Search Console. If it doesn't, don't assume it does — plan on spatie/laravel-sitemap or similar alongside.

Testing. Write one feature test per integrated model asserting the rendered <head> contains the expected tags and, critically, that a record with empty SEO falls back rather than emitting <meta name="description" content="">. The empty-string case is the most common defect in these modules and is invisible in a browser.

Gotchas and Tips

Adoption signals are the headline risk. 0 stars, 0 dependents, and a last release in August 2024 means effectively no community surface: no Stack Overflow answers, no third-party blog posts, no one else hitting your bug. If the package is critical to your admin, fork it into your own namespace or pin it to an exact version ("ibecsystems/admin-kit-seo": "1.0.0", not ^1.0) so a surprise release can't break you mid-sprint. Budget for the possibility of maintaining it yourself.

Version-lock against the parent admin-kit. Companion packages break when the parent moves. Check the composer.json constraint on admin-kit and pin both together; a floating constraint on the parent is the most likely cause of "worked yesterday" failures.

Config caching surprises. If the package registers routes, view composers, or morph maps conditionally on config, php artisan config:cache in production can change behavior versus local. Reproduce any discrepancy with php artisan config:clear first, and always re-cache after editing published config.

Publish conflicts on upgrade. Because you'll likely publish migrations and config, a package update that ships new migrations can collide with your published ones. Keep a note of what you published and when; diff the package's database/migrations against database/migrations on every version bump.

Morph map breakage. If the package or your app uses Relation::enforceMorphMap(), the trait's stored model_type values must match your aliases. Adding a morph map after records exist silently orphans their SEO rows — they'll still be in the DB but unreachable. Set the morph map before seeding anything.

Duplicate tags from overlapping packages. If you already run spatie/laravel-seo, artesaos/seotools, or hand-rolled meta in your layout, you will get two <meta name="description"> tags and search engines will pick unpredictably. Pick one owner for <head> and strip the others in the same PR that installs this package.

Escape hatches to look for. Three extension points determine how painful this package will be long-term: (a) can you override the published views without editing vendor files, (b) is the renderer a Blade directive, a helper, or a service you can swap in the container, and (c) does the config expose field-level toggles. If all three are missing, wrap the package behind your own thin service class from day one so you can replace it without touching call sites.

Debugging the missing-tag case. When a tag doesn't render, check in this order: is the trait actually on the model (not just the parent class), is the record's SEO row present ($model->seo in tinker), is the view partial actually included on that route's layout, and is a cached rendered page being served. That sequence resolves the overwhelming majority of "it's not showing up" reports and takes two minutes.

Treat silent fallbacks as a bug source. Well-meaning packages fall back to the record's title when no SEO title is set. That's often desirable — until a client asks why a page's meta title differs from its H1 and you can't find where it's coming from. Log or document the fallback chain in the config file comments so the next developer finds it in the config, not in vendor/.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect