Storage model: JSON, not shortcodes
A criticism regularly aimed at any page builder from the Classic Editor era goes like this:
Classic builders translate your layout into hundreds of nested shortcodes saved into
post_content. WordPress re-parses those brackets on every request, which hurts TTFB. And if you ever deactivate the builder, your database is left full of broken brackets.
That describes a real family of builders. It does not describe this one, and the difference is checkable in about thirty seconds — so this page states what is actually stored, then says plainly which parts of the criticism do land.
What is actually stored
Measured on a builder page in a running install:
builder JSON (post_meta) : 52,891 bytes
starts: [{"type":"section","_items":[{"type":"column","width":"1_1", …
post_content : 17,583 bytes
shortcode tags : 0
The layout lives in post meta, under fw:opt:ext:pb:page-builder:json, as a JSON tree of typed
items. post_content contains no shortcode tags at all.
You can verify it on any site:
SELECT LEFT(meta_value, 120) FROM wp_postmeta
WHERE meta_key = 'fw:opt:ext:pb:page-builder:json' LIMIT 1;
Shortcodes are a rendering step, not the storage format
Shortcodes do exist in the pipeline — they are generated from the JSON at render time, by
FW_Option_Type_Page_Builder::json_to_shortcodes(), and immediately turned into HTML. They are an
intermediate representation inside a single request, not something written to the database. The full
mechanics are in Data flow: edit → stored JSON → render.
That distinction is what makes the criticism miss:
| The claim | Reality here |
|---|---|
| "Shortcode soup fills your database" | The database holds a JSON tree. post_content carries no shortcode tags. |
| "Deactivate and you're left with thousands of broken brackets" | There are no brackets to leave behind. |
| "WordPress re-parses brackets every load, hurting TTFB" | Rendering starts from a parsed JSON tree, not from bracket-scanning post_content. |
| "Modern tools parse modular JSON objects instead" | That is precisely the model in use. |
The last row is the interesting one: storing structured JSON rather than markup is the criterion usually offered to define a modern builder, and it is the criterion this architecture already meets.
Structured storage buys more than a rebuttal. Because the layout is data rather than markup, it can be queried, diffed, migrated between value shapes, generated by the Site Converter, and re-rendered by a different renderer entirely — which is exactly how the same content appears through a Gutenberg block without a second implementation.
What the criticism does get right
Being straight about this matters more than winning the argument, and these are on the modernization plan:
- The builder canvas is imperative. Backbone + jQuery, not a reactive state engine. Storage is modern; the editing surface is the older layer.
- The Live Editor re-renders over the network. It uses AJAX and an iframe rather than a client-side state engine, so it behaves like the "legacy live editing" the criticism describes.
An earlier version of this page listed editing performance as a structural weakness. Measuring it showed otherwise, and the correction is worth keeping visible.
Opening an element's options modal cost ~6.7 MB and ~873 ms — but almost none of that was the framework's design. One tab (Animations) was 95% of it, because a picker control rendered every choice's sub-options eagerly, including the ~40 the user hadn't selected and that the save path never reads.
Deferring those unread variants took it to ~2.1 MB / ~137 ms — the same architecture, 6× faster, and 13× on the offending tab. It was a bug in one control, not a limit of server-rendered options.
The general lesson generalises past this framework: "the admin feels slow" gets attributed to a stack's age far more often than anyone profiles it.
- The builder mounts on the Classic Editor screen. A real coupling to a WordPress surface being de-emphasised over time.
- DOM depth is middling. A section renders roughly
section > .fw-container > .fw-row > …— about four levels. Leaner than the seven-deep wrappers of the builders usually cited, but not the two-or-three-tag ideal.
One further criterion already met: generated CSS is written to static files under
uploads/unysonplus/css/, not injected inline per page.
Judging a builder on more than one axis
"Modern" gets used as a single verdict when it is really four independent questions:
| Axis | Where this framework sits |
|---|---|
| Storage model | Structured JSON in post meta — strong |
| Output quality | Clean semantic HTML, static generated CSS, jQuery-free front end — good |
| Editing performance | Imperative canvas and a network-backed live editor; modal render is ~137 ms after profiling — the least modern axis, but not the bottleneck it looked like |
| Coupling to core | Mounted on the Classic Editor screen — a real dependency |
Those axes are not equally reversible, which is the point. An editing canvas can be replaced;
stored content cannot. A builder with a React canvas that writes shortcode markup into
post_content has locked in the part that is expensive to change and modernised the part that is
cheap. This framework did the opposite — which is why the roadmap targets the canvas and leaves the
storage model alone.