digit7s/filament-seo
digit7s/filament-seo brings SEO management into Filament admin panels, letting you add editable meta titles, descriptions, and social sharing tags to your resources so content teams can tune search snippets without touching code. Lightweight and simple to drop into existing resources.
digit7s/filament-seo v0.1.0 is a first public release, so treat the API as pre-1.0 and pin ^0.1. It gives you three things: a polymorphic SEO metadata table/model, Filament UI pieces (form fields, optional tabs, infolist section, status and score columns), and a Blade component that renders the stored metadata into a document <head>.
Minimal path:
composer require digit7s/filament-seo:^0.1
php artisan vendor:publish --tag=filament-seo-config
php artisan vendor:publish --tag=filament-seo-migrations
php artisan migrate
Check the version constraints before anything else — PHP 8.4+, Laravel 13, Filament 5. If your app is on an older Laravel/Filament pair, this will not install, so verify in CI before planning work around it.
Where to look first: the published config file (it controls the SEO model/table and likely image/disk behaviour) and the README's resource-integration example. Your first use case should be one Filament resource — a Page or Post — where you add the SEO form section to the resource schema, persist the polymorphic relation, then place <x-filament-seo::meta> once in that model's frontend layout <head>. Confirm the rendered tags with a quick curl or feature test before rolling it out to other resources.
Resource form integration. Add the package's SEO fields to your resource form, ideally inside the optional tabbed layout so the main content tab stays clean. Pair it with the infolist section on the view page and the status column on the table, so editors can see at a glance which records have metadata and which don't.
Polymorphic reuse across models. Because storage is polymorphic, one SEO table serves pages, posts, products, etc. Use the same form section partial/schema method across resources rather than duplicating field definitions, and define one Blade layout that renders the meta component for whichever model the view receives.
Explicit head placement. Put the component once in your base layout inside <head>, passing the current record:
<head>
...
<x-filament-seo::meta :model="$page" />
</head>
Every frontend layout that should emit tags needs this — there is no automatic injection.
Editorial workflow with the score column. Use the score column as a triage signal in the Filament table (sort or filter low scores) and the status column for publication readiness. Combine with a table filter on "missing description" style conditions if the package exposes them, otherwise sort by score ascending during content audits.
Image handling. Store Open Graph images on a public disk and save the resulting URL/path. The component validates public-disk image URLs and silently omits ones that don't resolve, which is the intended safety behaviour but also means a misconfigured disk produces no visible error on the page.
Testing. Add a feature test per frontend route asserting <title>, og:title, and canonical presence, plus one asserting the tags are absent when a record has no SEO row. This catches layout regressions where the component gets dropped from a template.
head hook. A missing tag on a live page usually means the layout wasn't updated, not that data is missing.composer why-not if install fails; don't try to force it with --ignore-platform-reqs in a Filament app.storage/app/private, or S3 without a public URL configured, will simply omit og:image. Verify the disk's url config and that php artisan storage:link has run for the local disk.noindex from publication status. If those fields are left blank, you get no tag — set them deliberately for paginated, filtered, or syndicated pages.spatie/laravel-sitemap and hand-written schema markup if you need those. The robots field is the meta tag only.php artisan config:clear (and in production, re-cache). Stale cached config is the classic reason published settings appear to have no effect.og:type, locale). Re-publishing migrations after an upgrade can overwrite local edits — diff before running the publish command.How can I help you explore Laravel packages today?