We built DEV3 AI Element Pack for WPBakery & Elementor as a WordPress plugin in PHP with a React admin, thin editor adapters for Elementor, WPBakery and the block editor, and a dependency-free front-end script. The design rests on one rule: every element is described once, as data, and everything else is derived from that description.
Key design decisions
- A builder-neutral field schema. Each element is a list of fields from 12 types (text, textarea, rich text, number, select, toggle, colour, image, icon, link, date and repeater) with limits, groups and AI hints. The Elementor adapter turns those fields into controls, the WPBakery adapter into
vc_map() params, and the block stores them as one settings object.
- One canonical value shape.
Normalizer accepts every builder's native shape and returns one canonical value: a WPBakery vc_link string and an Elementor {url, is_external, nofollow} array both become {url, external, nofollow}; an attachment id and an Elementor media array both become {id, url, alt}; a url-encoded param_group and an Elementor repeater both become a list of normalised items.
- One renderer. The Elementor widget, the WPBakery shortcode, the
DEV3 Element block and the admin playground all call Renderer::render(), which escapes every value and wraps the output in the same classes and CSS custom properties.
- Converters for the other direction.
Converter turns canonical settings back into each builder's saved shape. Templates, "Create page" and the AI write-back use it, so one template exports to Elementor data, WPBakery shortcodes or block markup.
- AI drafts that follow the schema. The Fill this element response schema is generated from the same fields: types,
maxLength, item counts and an icon enum. Links, images and style fields are never sent to the model to invent. The draft goes through the normaliser and is shown as a diff; nothing is written until the user accepts.
- Design tokens instead of per-element styling. The brand kit (colours, radius, shadow, fonts) is printed as CSS custom properties that every element reads. Named presets restyle any element, and colours that fail WCAG AA contrast trigger a warning.
Architecture
Elements are registered from four packs (Content, Interactive, Media, Marketing) into a registry that can switch single elements off. On the front end, styles and the deferred script are enqueued in the head only when the queried post contains a DEV3 shortcode, block or Elementor widget, and late renders fall back to a footer enqueue. Row extras (parallax, video backgrounds, gradients, shape dividers and sticky rows) hook into Elementor sections and containers, WPBakery rows and a DEV3 Section block. Built-in icons are inline SVG; uploaded SVG sets are sanitised and Fontello or IcoMoon fonts load only where one of their icons is used. The API client, encrypted key storage, usage log and monthly budget cap come from a shared core used across DEV3's plugins.