Looking to hire Laravel developers? Try LaraJobs
This package is not available.

laravel-seo maintained by kreetancraft

Description
SEO for Laravel — per-model meta, live content analysis, JSON-LD and a sitemap feed. Livewire 4 + Flux UI.
Last update
2026/08/29 11:39 (dev-main)
License
Links
Downloads
7

Comments
comments powered by Disqus

Laravel SEO

Per-model SEO metadata, live content analysis, Google and social previews, JSON-LD helpers and a sitemap feed. Livewire 4 + Flux UI.

Ships no models of its own beyond SeoMeta, no layout, no CSS and no image handling — it renders into your application and knows nothing about your content types until you tell it.

Design decisions worth knowing before you install

It knows nothing about your content types. The bulk screen and seo:analyze read a registry that ships empty. A package that owns a content type contributes to it through a container tag, so neither package names the other.

It names no permission of its own. The screens ask the ordinary authorization question and SeoPolicy answers it. Until permissions exist anywhere in the app it is open, so it works on a bare install rather than failing closed.

It ships no image handling. og:image resolves through seo.image_resolver when one is configured, and falls back to the model's own default otherwise.

Flux is a hard dependency. The views use <flux:*> throughout.

Installation

composer require kreetancraft/laravel-seo
php artisan migrate

Let Tailwind see this package

Required. Tailwind v4 generates only the classes it finds by scanning files, and it does not scan vendor/. In resources/css/app.css:

@source '../../vendor/kreetancraft/laravel-seo/resources/views';

Skipping it fails confusingly rather than loudly — classes shared with your own views still work and only the ones unique to this package go missing.

Making a model SEO-aware

use Kreetancraft\Seo\Concerns\HasSeo;

class Article extends Model
{
    use HasSeo;

    public function seoDefaults(): array
    {
        return [
            'title' => $this->title,
            'description' => $this->excerpt,
            'path' => '/articles/'.$this->slug,
            'image' => null,
        ];
    }
}

Then register it so it appears on the bulk screen — from a package, through the tag:

$this->app->bind('acme.seo.models', fn () => [
    Article::class => [
        'label' => 'Article',
        'title' => 'title',
        'edit_route' => 'admin.articles.edit',
        'route_param' => true,
    ],
]);

$this->app->tag('acme.seo.models', \Kreetancraft\Seo\Support\SeoModelRegistry::TAG);

Or from a host application, in config/seo.php under models.

The editor

Add the SEO card to any Livewire form:

use Kreetancraft\Seo\Livewire\Concerns\InteractsWithSeoForm;

class EditArticle extends Component
{
    use InteractsWithSeoForm;
}
@include('seo::livewire.partials.seo-fields', ['seoAnalysis' => $this->seoAnalysis()])

That gives you meta fields, Open Graph and X/Twitter overrides, noindex/nofollow, live Google and social previews, and the analysis panel. Pass ['compact' => true] to drop the previews and analysis for a modal.

What gets analysed

Thirteen content checks — meta title present and length, meta description present and length, focus keyword in title, description, slug, content and headings, content length, headings present, image alt text, links — plus four readability checks: sentence length, paragraph length, passive voice and transition words.

Add your own by tagging it:

$this->app->tag([MyCheck::class], 'seo.checks.content');

Site health

<livewire:seo.health />

Average score, how much content has no meta title or description, and how much is unscored — counted across every registered model, not just rows that already have meta.

The sitemap feed

GET /api/v1/sitemap returns every public URL with lastmod. Contribute to it by implementing ProvidesSitemapUrls and tagging the class:

$this->app->bind('acme.sitemap', fn () => ArticleSitemapProvider::class);
$this->app->tag('acme.sitemap', \Kreetancraft\Seo\Support\SitemapProviderRegistry::TAG);

Permissions

SeoPolicy declares PERMISSION_SUBJECT = 'seo', so with kreetancraft/laravel-user-management installed one command creates view-seo, create-seo, update-seo and delete-seo:

php artisan user-management:sync-permissions

A SEO link also appears in that package's sidebar, with nothing declared on either side.

Images

// config/seo.php
'image_resolver' => \Kreetancraft\Media\Support\MediaImageResolver::class,
'og_picker_view' => 'components.my-media-picker',

Leave both null and og:image falls back to whatever seoDefaults()['image'] returns.

Requirements

PHP 8.2+, Laravel 12 or 13, Livewire 4, Flux 2.

License

MIT.