PHPackages                             blackpig-creatif/sceau - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. blackpig-creatif/sceau

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

blackpig-creatif/sceau
======================

SEO and social media optimization for FilamentPHP v5

v2.0.0(1mo ago)030MITPHPPHP ^8.3|^8.4

Since Feb 9Pushed 1mo agoCompare

[ Source](https://github.com/Blackpig/sceau)[ Packagist](https://packagist.org/packages/blackpig-creatif/sceau)[ Docs](https://github.com/blackpig-creatif/sceau)[ RSS](/packages/blackpig-creatif-sceau/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (9)Dependencies (22)Versions (13)Used By (0)

Sceau
=====

[](#sceau)

**SEO metadata management plugin for FilamentPHP v5**

Sceau provides comprehensive SEO metadata management for Laravel applications using Filament v5. It offers a polymorphic approach to SEO data, allowing any Eloquent model to have associated meta tags, Open Graph data, Twitter Cards, and JSON-LD structured data.

Features
--------

[](#features)

- **Polymorphic SEO Data** - Attach SEO metadata to any Eloquent model
- **Filament Integration** - Manage SEO through a clean RelationManager interface
- **Meta Tags** - Title, description, canonical URLs, robots directives
- **Social Media** - Open Graph and Twitter Card support
- **Structured Data** - Extensible JSON-LD schema generators for Schema.org markup
- **Settings Management** - Database-backed global SEO settings via Filament panel
- **Image Processing** - Integrated with Chambre Noir for optimized OG/Twitter images
- **Atelier Integration** - Automatic schema generation from content blocks with no controller boilerplate
- **Blade Component** - Simple `@seo($model)` directive for frontend rendering

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 11.0+ or 12.0+
- Filament 5.0+

Installation
------------

[](#installation)

```
composer require blackpig-creatif/sceau
```

Run the migration:

```
php artisan migrate
```

Optionally publish the config file:

```
php artisan vendor:publish --tag=sceau-config
```

Basic Usage
-----------

[](#basic-usage)

### 1. Add the Trait to Your Model

[](#1-add-the-trait-to-your-model)

```
use BlackpigCreatif\Sceau\Concerns\HasSeoData;

class Page extends Model
{
    use HasSeoData;
}
```

### 2. Add the RelationManager to Your Filament Resource

[](#2-add-the-relationmanager-to-your-filament-resource)

```
use BlackpigCreatif\Sceau\Filament\RelationManagers\SeoDataRelationManager;

class PageResource extends Resource
{
    public static function getRelations(): array
    {
        return [
            SeoDataRelationManager::class,
        ];
    }
}
```

### 3. Render SEO Tags in Your Layout

[](#3-render-seo-tags-in-your-layout)

```

    @seo($page)

```

Or use the component directly:

```

```

Configuration
-------------

[](#configuration)

The config file (`config/sceau.php`) allows you to customize:

- **Upload disk and directory** for OG/Twitter images
- **Character limits** for titles and descriptions
- **Default values** for robots directives, OG types, Twitter card types
- **Available schema types** (filter which types appear in the select)

### Global SEO Settings

[](#global-seo-settings)

Sceau includes a settings page accessible from your Filament panel at **Settings &gt; SEO Settings**. Configure:

- Site name and URL
- Contact information (phone, email)
- Business address
- Price range and opening hours (for LocalBusiness schema)

To add the settings page to your panel, register the plugin:

```
use BlackpigCreatif\Sceau\SceauPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        ->plugins([
            SceauPlugin::make(),
        ]);
}
```

Schema Architecture
-------------------

[](#schema-architecture)

Sceau uses a **dual-layer approach** to schema generation:

1. **Model-Level Schemas** (SeoData) - For entity-specific metadata (Organization, LocalBusiness, Product models)
2. **Runtime Schemas** (SchemaStack) - For page-specific content assembled at request time

This separation aligns with how modern web applications work: pages are built dynamically from blocks, products are fetched by controllers, and breadcrumbs depend on the current route.

### Model-Level Schemas (SeoData)

[](#model-level-schemas-seodata)

These schemas describe entities that exist as models in your database:

- **Organization** - Company/organization data from settings
- **LocalBusiness** - Business with address/hours from settings
- **Product** - For dedicated Product models with SEO data
- **Person** - For author/profile models

Configure these through the Filament RelationManager on your models.

### Runtime Schemas (SchemaStack)

[](#runtime-schemas-schemastack)

These schemas describe content assembled at runtime:

- **Article/BlogPosting** - Built from Atelier blocks
- **ItemList** - Product listings, search results
- **BreadcrumbList** - Navigation breadcrumbs
- **FAQPage** - FAQ blocks on pages
- **VideoObject** - Video blocks

Runtime Schema Generation
-------------------------

[](#runtime-schema-generation)

### The Schema Facade

[](#the-schema-facade)

Push schemas onto the stack during request processing:

```
use BlackpigCreatif\Sceau\Facades\Schema;

public function show(Page $page)
{
    $products = Product::where('category_id', $page->category_id)->paginate(24);

    Schema::push([
        '@context' => 'https://schema.org',
        '@type' => 'ItemList',
        'numberOfItems' => $products->total(),
        'itemListElement' => $products->map(fn ($product, $index) => [
            '@type' => 'ListItem',
            'position' => $index + 1,
            'item' => [
                '@type' => 'Product',
                'name' => $product->name,
                'url' => route('products.show', $product),
            ],
        ])->values()->toArray(),
    ]);

    return view('pages.show', compact('page', 'products'));
}
```

### Runtime Schema Helpers

[](#runtime-schema-helpers)

Use helper classes for common patterns:

```
use BlackpigCreatif\Sceau\Facades\Schema;
use BlackpigCreatif\Sceau\Schemas\Runtime\ProductListSchema;
use BlackpigCreatif\Sceau\Schemas\Runtime\BreadcrumbListSchema;

public function show(Page $page)
{
    $products = Product::paginate(24);

    Schema::push(ProductListSchema::makeDetailed($products));

    Schema::push(BreadcrumbListSchema::make([
        ['name' => 'Home', 'url' => route('home')],
        ['name' => 'Products', 'url' => route('products.index')],
        ['name' => $page->category->name, 'url' => route('category', $page->category)],
    ]));

    return view('pages.show', compact('page', 'products'));
}
```

**Available helpers:**

- `ArticleSchema::fromBlocks($blocks, $seoData)` - Generate Article from Atelier blocks
- `ProductListSchema::make($products, $transformer)` - Generate ItemList
- `ProductListSchema::makeDetailed($products)` - ItemList with pricing/images
- `BreadcrumbListSchema::make($breadcrumbs)` - Generate BreadcrumbList

### Multiple Schemas Per Page

[](#multiple-schemas-per-page)

Schema.org supports (and Google expects) multiple independent schemas on a single page:

```
public function show(Page $page)
{
    // Article content + typed block schemas from Atelier (auto-wired via Head component)

    // Additional runtime schemas pushed from the controller
    Schema::push(ProductListSchema::make($featuredProducts));

    Schema::push(BreadcrumbListSchema::make($breadcrumbs));
}
```

Final output will be an array of schemas, each validated independently by Google.

---

Atelier Block Integration
-------------------------

[](#atelier-block-integration)

When [Atelier](https://github.com/blackpig-creatif/atelier) is installed alongside Sceau, the `` component automatically generates Schema.org output from your page's blocks. No controller code is required.

```
{{-- This is all you need --}}

```

For the complete integration reference, see [docs/atelier-integration.md](docs/atelier-integration.md).

### How it works

[](#how-it-works)

The `Head` component calls `PageSchemaBuilder::build($page)` automatically for any model that has `publishedBlocks`. The builder runs three passes over the blocks:

1. **Article schema** — assembled from all blocks implementing `HasCompositeSchema` (text content, image URLs)
2. **Legacy standalone schemas** — blocks implementing `HasStandaloneSchema` that build the full schema array themselves
3. **Driver-based typed schemas** — blocks implementing `HasSchemaContribution` that declare a `SchemaType` and provide data; `SceauBlockSchemaDriver` constructs the schema array using Sceau's generators

### Wiring the driver

[](#wiring-the-driver)

In your application's `config/atelier.php`:

```
'schema_driver' => \BlackpigCreatif\Sceau\Schema\Drivers\SceauBlockSchemaDriver::class,
```

This registers `SceauBlockSchemaDriver` as the singleton implementation of `BlockSchemaDriverInterface`. The driver matches on `SchemaType` value and delegates construction to Sceau's schema generators.

### Built-in block schemas

[](#built-in-block-schemas)

BlockSchema output`TextBlock`Article body text`TextWithImageBlock`Article body text + image`TextWithTwoImagesBlock`Article body text + two images`GalleryBlock`Article image URLs`CarouselBlock`Article image URLs`VideoBlock``VideoObject``FaqsBlock``FAQPage`### Adding a new SchemaType

[](#adding-a-new-schematype)

To support a new type in `SceauBlockSchemaDriver`:

1. Add a case to the `match` expression in `resolveSchema()`
2. Add a `protected buildXxxSchema(array $data): ?array` method
3. Add a `fromXxx(array $data): array` static method to the corresponding schema generator

---

Extending SeoData Schemas
-------------------------

[](#extending-seodata-schemas)

### Overriding Methods in a Subclass

[](#overriding-methods-in-a-subclass)

Create a local schema class that extends one of the base generators:

```
namespace App\SEO\Schemas;

use BlackpigCreatif\Sceau\SchemaGenerators\ArticleSchema;
use BlackpigCreatif\Sceau\Models\SeoData;

class CustomArticleSchema extends ArticleSchema
{
    protected function getAuthor(SeoData $seoData): array|null
    {
        $page = $seoData->seoable;

        if ($page->authors && $page->authors->count() > 0) {
            return $page->authors->map(fn ($author) => [
                '@type' => 'Person',
                'name'  => $author->name,
                'url'   => route('authors.show', $author),
            ])->toArray();
        }

        return parent::getAuthor($seoData);
    }
}
```

Register your custom schema in `AppServiceProvider`:

```
use BlackpigCreatif\Sceau\Services\JsonLdGenerator;
use BlackpigCreatif\Sceau\Enums\SchemaType;
use App\SEO\Schemas\CustomArticleSchema;

public function boot(): void
{
    $generator = app(JsonLdGenerator::class);
    $generator->registerGenerator(
        SchemaType::Article,
        new CustomArticleSchema
    );
}
```

### Creating Custom Schema Types

[](#creating-custom-schema-types)

For schema types not included in the package:

```
namespace App\SEO\Schemas;

use BlackpigCreatif\Sceau\SchemaGenerators\BaseSchema;
use BlackpigCreatif\Sceau\Models\SeoData;

class CourseSchema extends BaseSchema
{
    public function getType(): string
    {
        return 'Course';
    }

    public function generate(SeoData $seoData): array
    {
        $schema = $this->baseSchema();
        $course = $seoData->seoable;

        $schema['name']        = $this->getName($seoData);
        $schema['description'] = $this->getDescription($seoData);
        $schema['provider']    = [
            '@type' => 'Organization',
            'name'  => config('app.name'),
        ];

        if ($course->price) {
            $schema['offers'] = [
                '@type'         => 'Offer',
                'price'         => $course->price,
                'priceCurrency' => 'USD',
            ];
        }

        return $this->removeNullValues($schema);
    }
}
```

### Container Binding for Global Override

[](#container-binding-for-global-override)

To replace a schema generator globally without touching the package:

```
use BlackpigCreatif\Sceau\SchemaGenerators\ArticleSchema;
use App\SEO\Schemas\CustomArticleSchema;

public function register(): void
{
    $this->app->bind(ArticleSchema::class, CustomArticleSchema::class);
}
```

---

Accessing SEO Data
------------------

[](#accessing-seo-data)

The `HasSeoData` trait provides convenient accessor methods:

```
$page = Page::with('seoData')->first();

$title       = $page->getSeoTitle();        // Falls back to $page->title or $page->name
$description = $page->getSeoDescription();
$hasSchema   = $page->seoData?->hasSchemaMarkup();
$hasFaq      = $page->seoData?->hasFaqPairs();

$ogTitle = $page->getSeoAttribute('open_graph.title', 'Default Title');
```

Advanced: Image Resolution
--------------------------

[](#advanced-image-resolution)

Sceau integrates with **Chambre Noir** for image processing and supports **Atelier** blocks for hero image resolution.

When rendering OG/Twitter images, the package will:

1. Check for explicitly uploaded images in SEO data
2. Fall back to the first published Atelier hero block's background image
3. Apply the appropriate Chambre Noir conversion (`og`, `twitter`, etc.)

Override this behavior by extending `SeoData` and customizing the image resolution methods.

---

Documentation
-------------

[](#documentation)

- [Atelier Integration](docs/atelier-integration.md) -- automatic block schema generation reference

---

License
-------

[](#license)

MIT License. See [LICENSE](LICENSE) for details.

###  Health Score

44

—

FairBetter than 92% of packages

Maintenance90

Actively maintained with recent releases

Popularity10

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity58

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~7 days

Total

8

Last Release

48d ago

Major Versions

v1.1.2 → v2.0.02026-04-01

PHP version history (2 changes)v1.0.0PHP ^8.2|^8.3|^8.4

v2.0.0PHP ^8.3|^8.4

### Community

Maintainers

![](https://www.gravatar.com/avatar/e094a144c7d16d2115fac66e49bf5013829a545f111c618ff22fe11ddf8c7bf4?d=identicon)[Blackpig](/maintainers/Blackpig)

---

Top Contributors

[![Blackpig](https://avatars.githubusercontent.com/u/1029317?v=4)](https://github.com/Blackpig "Blackpig (10 commits)")

---

Tags

laravelseosocial mediafilamentfilamentphpopen-graphmeta-tagstwitter cardsblackpig-creatifsceau

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/blackpig-creatif-sceau/health.svg)

```
[![Health](https://phpackages.com/badges/blackpig-creatif-sceau/health.svg)](https://phpackages.com/packages/blackpig-creatif-sceau)
```

###  Alternatives

[dotswan/filament-map-picker

Easily pick and retrieve geo-coordinates using a map-based interface in your Filament applications.

124139.3k2](/packages/dotswan-filament-map-picker)[pboivin/filament-peek

Full-screen page preview modal for Filament

253319.6k12](/packages/pboivin-filament-peek)[larament/seokit

A complete SEO package for Laravel, covering everything from meta tags to social sharing and structured data.

411.9k](/packages/larament-seokit)[creagia/filament-code-field

A Filamentphp input field to edit or view code data.

58289.3k3](/packages/creagia-filament-code-field)[jibaymcs/filament-tour

Bring the power of DriverJs to your Filament panels and start a tour !

12247.8k](/packages/jibaymcs-filament-tour)[swisnl/filament-backgrounds

Beautiful backgrounds for Filament auth pages

54149.2k6](/packages/swisnl-filament-backgrounds)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
