Skip to content

Filament Atelier

The audit found four blockers and one 200 that should have been a 404

18 August 2026 Updated 18 August 2026 4 min read
The Atelier task breakdown with status markers, next to a terminal showing a nested URL returning the wrong page.

I read every task file against the actual code instead of against memory. Four things marked as done were not, and each was quietly blocking a later feature. Then a nested URL turned out to return 200 with the wrong page rendered, which is worse than the 404 I was expecting.

v0.1.2 is out. It exists because I stopped building and read the task files against the code instead of against memory.

The task breakdown had ten feature files with checkboxes. Most of them were written before the code existed and never revisited. So I went through every one, opened the files it described, and marked what was actually true.

Four items were marked or assumed done and were not. Each was blocking something later, which is why they mattered more than their size suggested.

The bug I found on the way

While checking the routing claims I tried a nested slug, /services/web-design, expecting a 404 because nested pages were never built.

It returned 200 with the services page rendered.

The route is /{locale}/{slug?}. Laravel bound locale to services and slug to web-design. The controller saw that services is not a configured locale, reassigned the slug to that first segment, and threw the rest of the path away.

A 404 tells you a page does not exist. A 200 with the wrong content tells a crawler that two URLs are the same page and tells a client their new page is broken in a way they cannot describe. The fix is that a slug is now the whole path after the locale, so services/web-design is one row in the slugs table like any other and needs no parent relationship.

I would not have found it by building features. I found it by trying to confirm a sentence in a document.

Design tokens, because the preview was lying by luck

The whole argument for this project is that the editor preview renders the real page. That holds only if both sides read the same source for colour and spacing.

They did not. They both read hardcoded Tailwind classes, which is not the same thing as sharing a source, it is two copies that happen to match. The first time somebody restyled a client site, the preview would drift.

Tokens are now emitted as CSS custom properties into the head of the layout that both the preview and the public page use. Defaults live in PHP, config overrides them key by key, so changing one colour does not mean restating the rest and an existing install picks them up without republishing anything.

A block stores a reference rather than a value:

"background": { "token": "color.primary" }

The renderer turns that into var(--atelier-color-primary) before the view runs. Which means changing a palette is a config edit rather than a data migration.

Shared controls, and why they emit inline styles

Blocks declared a supports() method from the start. Nothing read it. So every block that wanted a background colour would have grown its own field, which is exactly how a page builder turns into Elementor.

Now a block opts in and gets those controls built once. The decision worth writing down is what they emit: an inline style built from tokens, never a utility class.

A class written in PHP is a class Tailwind never scans. It would compile in my example app, where the class also appears in a Blade file, and vanish on a client site where it does not. That failure is invisible in development and total in production.

Revisions, and a delete confirmation that was telling the truth

Publishing overwrote the published copy with no snapshot. The editor's delete confirmation said the action was not reversible, and it was correct.

Every publish now snapshots the tree that went live, with who published it, pruned to a configurable count. Restoring copies a revision back into the draft, deliberately not into the live page, because restoring is an undo you then look at and publish rather than a silent change to a public site.

There is no UI for browsing them yet. The data is kept, which is the half that cannot be added retroactively.

What the audit changed about the docs

Every task file now carries a dated banner with what is genuinely built, and the index has a "what blocks what" section. Three of the four gaps above were holding up features scheduled after them, and none of that was visible from the checkboxes.

The other thing it produced: a list of work that had no home. CI, a security policy, a changelog and the documentation surface are not features, so no task file covered them, and they went untracked until an external audit named most of them. That is now a section in the foundation file rather than nowhere.

Where it stands

v0.1.2. Design tokens, shared section controls, page revisions, and a nested slug that resolves to the page you asked for.

The release adds a table, so it needs a vendor:publish and a migrate. New tables ship as new migration files rather than edits to one that already ran, which is the only version of this that is safe on somebody else's database.