Abdulkader Safi

What is left, and the things I am not going to build

Seven releases in eight days took Atelier from an MVP to something with a sitemap, structured data, revisions and CI. This is the honest state of it: what works, what is missing, what is deliberately refused, and the two gaps I cannot close by writing more code.

5 min read

Share
A roadmap board showing shipped features, missing features and deliberately refused ones for the Atelier page builder.

Atelier went from v0.1.1 to v0.3.0 in about a week. Design tokens, shared section controls, revisions, a sitemap, redirects, multiple layouts, structured data, CI, a security policy. 122 tests.

This is where it actually stands, and what comes next.

What works

A page is a JSON tree of typed blocks rendered by Blade at request time. Nine blocks. A three-pane editor with a live preview that renders the real page through the real layout and the real stylesheet. English and Arabic in one tree with dir="rtl" and hreflang. Draft and published as separate columns, so editing cannot touch a live page. Design tokens read by the editor and the front end from the same place. Multiple layouts picked per page. A sitemap, robots.txt, per-page indexing control, 301s when a slug changes, and a JSON-LD graph on every page.

That is enough to build a client site on. I would.

What is missing and should exist

Four blocks. Header, footer, contact form and raw HTML. The last one is the escape hatch the spec named for one-off markup, so right now there is no way to put arbitrary markup on a page at all, which is a real limitation with a one-hour fix.

Drag to reorder. It is arrow buttons. They work and persist correctly, but "drag a section up and the page reorders in front of you" is what the plan asked for, and buttons are not that. Adding a section also always appends, so putting one in the middle of a twelve-section page means clicking up eleven times.

A revisions UI. Snapshots are written on every publish and restoring works from code. There is no screen for browsing or comparing them, which means the delete confirmation in the editor is still telling the truth about being permanent.

Language files. This one came from filling in the plugin directory submission and deciding not to tick the translation support box. Atelier translates the content a client writes; its own interface is hardcoded English. Those are different features that share a word, and the honest fix is publishable lang files.

Performance work. Per-block asset loading, a page cache, and actual numbers. There are no Lighthouse figures recorded anywhere, so optimising now would be guessing. Measure first.

What I am not going to build

Review schema from testimonials. Google ignores reviews a business publishes about itself, and the block has no rating field. It would be markup that is at best ignored and at worst a manual action.

HowTo schema. Its rich results were dropped in September 2023. Markup for nobody.

Animation as a plugin feature. This was planned as a dropdown of GSAP presets and is now formally dropped. A block is already your PHP class and your Blade view, so it animates however you like without a preset system in the way. The cost, stated plainly, is that there is no animation control for a client.

A submissions table for the contact form. The block will be presentational, posting to a route you wire per site. Your app already knows how to store a submission, and a page builder that quietly becomes a data processor is a liability on every client site it ships to.

Block types authored from the panel. That is v2 and it is parked on purpose. It has its own security problems, starting with the fact that compiling user input as a template turns a textarea into remote code execution. The raw HTML block is the v1 answer.

The two gaps I cannot close by writing code

Nobody who is not me has used the editor. The verification plan has a run where somebody who has never seen it builds a page with hero, features, testimonials, CTA and FAQ, and publishes it, with no help and no documentation. Watch, do not assist, write down every hesitation. If that run goes perfectly first time, either the tester was coached or the task was too easy.

Nothing has been validated by Google. The structured data has 122 tests covering the shape of the graph. Neither the Rich Results Test nor the Schema.org validator has seen it, because both need a public URL. Those tools answer different questions too: one tells you what Google will do with it, the other whether it is correct.

Both of those are worth more than the next feature, and neither is something I can finish alone at a keyboard.

The pattern in this week

Looking back at seven releases, the useful bugs were not found by testing. They were found by using the thing.

The nested slug returning 200 with the wrong page: found while checking whether a sentence in a document was true. The head vanishing when a layout is replaced: found from a report that a social share image was not appearing. The preview crashing on a custom layout: found because writing a second layout gave a reason to read $page. The catch-all shadowing every application route since the first release: found while adding a demo blog route to a test app.

Every one of those was in a path I had never walked, and each was invisible from inside the code. The lesson I keep relearning is that building the next feature is a better bug-finding tool than staring at the last one.

Next

Fix the four missing blocks, do drag to reorder, then get somebody else in front of the editor and watch.

Last updated 18 Aug 2026 · filed under Laravel, filamentphp, plugin, tools, web application, ui, ux

Every entry on this project

28 build notes, in order

Including the ones where nothing worked. You are on part 13.

Read the series →

FAQ

Frequently asked questions

Should a page builder store contact form submissions itself?

Usually not. The application it installs into already knows how to store a submission, validate it, notify somebody and satisfy whatever retention rules apply to that client. A builder that adds its own submissions table duplicates all of it, and quietly takes on spam handling, export, deletion requests and data protection obligations on every site it ships to. A presentational block that renders the form and posts to a route the developer wires is far less code and keeps responsibility where the knowledge is. The exception is a product deliberately sold as a forms tool, which is a different product.

Why avoid letting users create block types from the admin panel?

Because the obvious implementation compiles user input as a template, and in most frameworks that means turning a textarea into remote code execution. There are safer designs, such as extracting placeholders with a parser and rendering through a restricted templating layer, but they are a project rather than a feature and they bring their own problems around styling, since utility class frameworks generate CSS by scanning source files that user-authored templates are not. Shipping a raw HTML block covers the one-off markup case immediately, and keeps the dangerous version as a deliberate decision rather than an accident.

How do you find bugs that a test suite will not catch?

Use the software in a way you have not before, particularly in the paths a new user hits first. Across seven releases here the significant bugs all came from that: a nested URL checked while verifying a claim in a document, a missing head found from a report about a social share image, a preview crash exposed by writing a second layout, and a routing conflict found by adding a demo route to a test application. Each sat in a path the author never walked, because a seeder or a fixture walked it instead. Building the next feature exercises the last one differently, which is why it finds more than staring at it does.

What does it mean for a plugin to support translation?

It means the plugin's own interface strings can be localised, normally through publishable language files, so installing it in a non-English panel produces a localised admin. It does not mean the plugin manages multilingual content. Those are separate features that share a word, and conflating them misleads anyone filtering a directory for the first. A page builder can store content in five languages, mirror right to left layouts and emit hreflang tags while every label in its own interface is a hardcoded English string, which is exactly the position this one is in until language files exist.

Written by

Abdulkader Safi

Software Engineer

Lead engineer at DSRPT, from Lebanon and based in Kuwait. I write about the tools and bugs from real client work, with the numbers I measured.

About me → GitHub LinkedIn

Need this kind of work done on your project?

Start a project →

Keep reading

More from Filament Atelier

All 28 entries →
  • A version number changing from 0.5.0 to 1.0.0 beside a list of deferred items.
    Filament Atelier

    · part 28 of 28

    Tagging 1.0.0 with four features missing, on purpose

    The gate list had thirteen items. Six went in, seven did not, and the tag went out anyway. What the number promises is that the API stops moving, not that the feature list is finished, and conflating those two is how packages sit at 0.x for three years.

  • The same block of JavaScript appearing in three different Blade layout files.
    Filament Atelier

    · part 26 of 28

    A script in three layouts is a contract nobody signed

    The editor's preview needed a few lines of JavaScript in the page it renders. I put them in the shipped layout, then copied them into two more. Anyone writing their own layout had to copy them too, and missing them broke half the editor with no error at all.