Skip to content

Filament Atelier

The config invited you to delete your own head tags

18 August 2026 Updated 18 August 2026 3 min read
Two rendered page sources side by side, one through the packaged layout and one through a host application layout, with identical head tags.

A social share image was not showing up. The render path turned out to be correct and the tag was never reaching the page, because the layout had been replaced. Every meta tag lived inside Atelier's own layout view, and a config key openly invited you to swap that view out.

This one started as a bug report against myself: I set a social share image on a page and no og:image appeared.

The first thing I did was prove the code worked. I ran the form save in a test, watched the file land at atelier/og/<ulid>.jpg in the right column, rendered the public page, and read the head:

<meta property="og:image" content="http://localhost:8000/storage/atelier/og/share.jpg">
<meta name="twitter:card" content="summary_large_image">

Correct. Which meant the bug was somewhere I had not looked, and the useful question was which of my assumptions was false.

The layout was the answer

Every meta tag lived inside atelier::layouts.site, Atelier's own layout view.

The config has a key called atelier.layout whose entire purpose is to let a host app point at its own Blade view, so a client site gets its own navigation and footer. That is the normal thing to do. It is documented, and I wrote it.

Doing it deleted the entire head. Title, description, canonical, hreflang, Open Graph, Twitter. All of it.

The page still rendered perfectly. That is the part that makes it bad rather than merely wrong: nothing errors, nothing is missing on screen, and the failure is only visible to a crawler or a share card. A site could run like that for months.

Previews stopped being noindex too, which is the same bug with worse consequences, because it means unfinished drafts become indexable.

Two partials, not one

The head moved into atelier::partials.meta. Design tokens moved into atelier::partials.tokens.

Splitting them was not tidiness. They have different positional requirements and one file cannot express both:

<head>
    @include('atelier::partials.meta')

    @vite(['resources/css/app.css'])

    {{-- After your stylesheet, so the tokens win. --}}
    @include('atelier::partials.tokens')
</head>

Meta does not care where it sits. Tokens must come after your stylesheet or the custom properties lose to it. One combined include would have to pick a position and be wrong about half its contents.

The test that matters

Three tests cover this, and one of them is the reason I trust the fix.

It renders the same page twice, once through Atelier's stock layout and once through a host app's own layout, extracts every meta, title, canonical and alternate line from both, and asserts the two lists are identical.

That is the test that fails if somebody adds a tag to one place and forgets the other. Asserting that "a custom layout has a title" would pass forever while the two drift apart.

The other two cover the specific things that were silently lost: the share image tag, and a preview still carrying noindex when a host app supplies the layout.

The second bug in the same area

While I was there: the share image upload was missing ->visibility('public'), which the package's own media helper sets everywhere else.

On a local disk that changes nothing. On S3 it means the upload succeeds, the tag is emitted, the URL is correct, and the image 403s for every crawler that fetches it. Works in development, broken in production, no error either way.

What I changed about the documentation

The README was describing a different product. It promised GSAP animations, a sitemap, JSON-LD, per-block asset loading, and header, footer, contact form and raw HTML blocks. None of those existed. It also said Filament v4 while composer.json requires ^5.0, which is the one that would actually break an install.

It now has a "Not built yet" section, because a page builder is judged on what it does not do and finding out after install is worse than reading it first.

Documentation also moved to the wiki, for a reason I had missed: Docs/ is export-ignored, so nobody who installs the package can read it. It was never written for using Atelier anyway; it is the spec, the task breakdown and the research behind the decisions.

The trap this leaves for anyone upgrading

If you point atelier.layout at your own view, this release needs two lines from you. Nothing breaks without them, which is exactly the problem: add them, or your pages keep rendering with no head at all.

That is at the top of the release notes rather than in a footnote, because the entire bug was that a silent failure looks like success.

Where it stands

v0.1.4. The head survives a custom layout, share images work on S3, and the README describes what ships.

Animation is now formally dropped as a plugin feature. A block is already your PHP class and your Blade view, so it animates however you like, and the plugin ships no GSAP dependency and no preset contract. The cost, stated plainly in the docs, is that there is no animation dropdown for a client.