- Non-destructive saves of existing pages/templates. The auto-fixer ran on every write and, when saving content it hadn't generated (an existing or cloned site), could silently rewrite element types, renumber IDs, and orphan the CSS/query references pointing at them — so a copy-only edit could change your layout. It now preserves existing content and reserves the aggressive repairs for new/imported content. (h/t @Lightning-Std, #13.)
- Element types are preserved.
divis a valid Bricks layout element (an unstyled<div>, distinct fromblock, a full-width flex div) — the auto-fixer no longer rewritesdiv → block, and the validator no longer rejectsname: "div". Theblock → containerpromotion (when flex properties are present) now runs only for new/imported content. (Note: the HTML→Bricks converter's<div>handling from 1.2.2 is unchanged — this is about the auto-fixer that runs on save.) - Element IDs are preserved. The "must contain a digit" rule is dropped as a gate — all-letter IDs (e.g.
wmhqxu) are valid in Bricks and are kept verbatim (the 6-character length is still enforced). When an ID genuinely must be regenerated (missing/malformed), every reference is rewritten in the same pass:brxe-<id>selectors in_cssCustom,queryId/filterQueryId/_cssId, and componentproperties— previously onlyparent/childrenwere updated, so self-referential CSS and loop/filter/pagination links silently broke. bricks_patch_pageaccepts existing (legacy) IDs in itsupdatearray. The strict "6 chars + digit" gate rejected the very IDs live on the page and forced a destructive full-page save; text-only patches now stay non-destructive (the patch path only auto-fixes newly added elements).
- Element types are preserved.
- Auto-fix now has a
preserve/normalizemode. Full saves of existing content (update_page/update_template) default topreserve(element types + IDs verbatim); new/imported/generated content (build / append / import) keepsnormalize(the aggressive structural repairs). Override per call with theautofix_modeparameter, or site-wide with thebab_autofix_modeoption /BAB_AUTOFIX_MODEconstant. Plugin 1.4.1 · MCP 1.2.4.
- CSS editability guard — keep agent-written CSS editable in the Bricks builder. Human-editable layout/responsive/visual CSS should live in a Bricks-native channel (element
_cssCustom, pagecustomCssviabricks_update_page_settings, or global classes) — not in the plugin-private_bab_page_assetsbundle, which is injected atwp_headpriority 9997 (before element CSS) and has no Bricks editing UI, so it silently overrides what the builder shows. The MCPbricks_update_page_assetsnow classifies thecssfield and warns when it carries editable rules (setBRICKS_MCP_BLOCK_EDITABLE_CSS=1to hard-block instead); the plugin enforces the same at the REST boundary viaBAB_GUARD_EDITABLE_CSS(offdefault /warn/block), so non-MCP callers are covered too. Reserve thecssfield for infra (@font-face,:root{--vars},@keyframes, critical CSS). (h/t the r/BricksBuilder feedback that plugin-managed page CSS a human can't edit defeats the purpose of using Bricks.)
- MCP steering: build global classes with native settings, not
_cssCustom. A global class's_cssCustomis not compiled into the page CSS via the API path (only its native settings are:_padding,_typography,_background,_gridTemplateColumns,_columnGap,_border,_boxShadow, …). Tool descriptions and the server preamble now steer toward the native-settings + element-_cssCustomchannels.
- HTML→Bricks converter: a plain
<div>is no longer forced into a flex container. The converter was blanket-mapping<div>(andnav/header/footer/main/article/aside/figure) to a Brickscontainer, which isdisplay: flex— so a plain block-flow wrapper silently inherited flex positioning it never had. It now maps those tags to ablock(a real<div>) and only reaches forcontainerwhen the resolved styles (inline or class-resolved from the provided stylesheet) actually lay it out as flex/grid. (h/t the r/BricksBuilder thread.)
- Connect: a "Plugin-managed page CSS" panel. The setup screen now lists pages that carry plugin-injected per-page CSS — the bundle stored in
_bab_page_assetsand echoed into<head>as<style id="bab-page-css-{ID}">. That CSS is intentionally not shown in the Bricks builder/settings/theme/class panels (it's for CSS variables, critical CSS and anything the assistant couldn't express via element/class settings), which is what made it feel like "CSS I can't find anywhere." It's read-only here (editable viabricks_update_page_assets), so it's no longer a black box.
- Connect — a guided setup UI. Turns the headless REST bridge into an admin screen ("Bricks MCP") so you don't have to wire everything by hand: a status grid (plugin / Bricks / REST endpoints / Application Passwords), one-click Application Password creation (copy button; the plaintext is shown once via a 120s transient — never via the URL — with a revoke table), a multi-client config generator with ready-to-paste config for Claude Code, Claude Desktop, Cursor, Windsurf, Cherry Studio and Hermes (pre-filled with your site URL, username and the generated password), a connection test, and an admin-bar status chip. Purely additive — it registers an admin menu only (no REST route or auth path touched), gated behind
is_admin()+ thebab_admin_ui_enabledflag. - Full-state backup & restore. Capture the whole Bricks layer (pages / templates / global classes / menus) plus a curated allowlist of WordPress core settings into one downloadable file, and restore it. The backup directory is hardened (
.htaccessdeny +index.php+ an unguessable token filename) and the settings dump deliberately excludes secrets / API keys.
- Spoofing-resistant client IP for rate-limiting & the login lockout. Proxy-forwarded headers (
X-Forwarded-For/CF-Connecting-IP/X-Real-IP) are now honored only from configured trusted proxies (thebab_trusted_proxiesconstant / option / filter; set it to'*'to restore the legacy behavior); otherwise the real TCP peer (REMOTE_ADDR) is used. Closes a bypass where a client could forgeX-Forwarded-Forto rotate the throttle key and defeat the login lockout. The REST and login throttles now key on the same source. - Object-level authorization on page-mutating endpoints.
update_page/patch_page/append_elements/clone_page/build_page/sign-codenow requireedit_poston the specific target page, not merely the genericedit_postscapability — so a lower-privileged user can no longer overwrite arbitrary pages by ID. Reads are unchanged; administrators are unaffected. - Backup restore is allowlist-based.
import_full_statenow writes only the same curated WordPress-core option keys the export captures (previously an infra-only denylist), so a crafted backup file can no longer set arbitrary options. - Backup filename token widened 6 → 20 characters (the only protection on nginx, where the directory's
.htaccessdeny is ignored). - Application Passwords force-enable is now opt-out-able via the
BAB_FORCE_APP_PASSWORDSconstant /bab_force_app_passwordsfilter (default unchanged), so a site can keep its deliberate decision to disable App Passwords.
- Custom
sites.jsonlocation — set theBRICKS_SITES_PATHenv var to keep your multi-site config outside the server folder (handy if you collect MCP servers in one shared directory). Accepts absolute, relative (to the working directory), or~-prefixed paths, and still falls back to the bundled./sites.jsonwhen unset, so existing setups are unaffected. When the variable is set but the file is missing, startup now fails loudly instead of silently falling back to theWORDPRESS_*vars — a path typo can no longer quietly connect you to the wrong site. Removes the need to symlinksites.jsoninto the repo folder. (h/t the r/BricksBuilder discussion on running the server under DDEV/opencode with a shared MCP-config folder.)
- Model steering toward native Bricks elements. The server now sends an MCP
instructionspreamble (injected into the client's system context, so it reaches any model on every request) telling the model to prefer Bricks' structured path — theme styles, global classes,settings.style, native elements liketext-link/button— over freelancing raw_cssCustom/inline styling. The same THEME-FIRST guidance now also rides onbricks_update_pageandbricks_patch_page, which previously had none (it was only on create/append/build). Closes the gap where models with weaker tool-calling discipline would inject custom CSS/classes instead of using the tools. (h/t the r/BricksBuilder DDEV/opencode thread.)
- Security audit — two new read-only tools:
bricks_security_auditandbricks_security_inventory. The audit scores the site 0–100 (A–F) across Bricks-core CVE exposure, bridge route permissions (a self-audit of the bridge's own write surfaces), code-element exposure, platform currency (WordPress core / PHP / plugin updates), configuration hygiene, and access/transport. Findings are returned worst-first with remediation; any open CRITICAL hard-caps the grade to F. It is a posture/exposure report, not a malware scanner. Outdated-component detection reads WordPress' own update transients — no external network calls. Plugin-side, behind thebab_security_audit_enabledoption (default on). - New bridge endpoints (admin-only):
GET /security/auditandGET /security/inventory/components. - Structured call/diff log — a new
bricks_call_logtool plus server-side logging of every tool call (summarized args, status, duration) and, for page-mutating calls, a before/after element diff (count delta + added/removed element IDs). Answers "which call changed or corrupted the page, and with what input?" — the trail a snapshot rollback erases. Light log for all calls is free (no extra requests); the before/after diff fires only for the page-data write tools and reuses a recent cached page read. Args are summarized (large arrays/strings collapsed) and the JSONL log rotates at 5 MB, so it stays compact. Best-effort and fail-safe — logging can never break a tool call. Flags:BAB_CALL_LOG=0to disable,BAB_CALL_LOG_DIFF=0to keep the light log without diffs,BAB_CALL_LOG_PATHto relocate the file. (h/t the r/BricksBuilder discussion on observability past 100 tools.) - These bring the MCP to 108 tools.
- Hardened code-surface routes (defense in depth). The
sign-codeand page-assetswrite endpoints now requiremanage_optionsinstead ofedit_posts, so signing executable Bricks code or storing raw page CSS/JS is restricted to administrators. Gated by thebab_harden_code_routesoption (default on); set it tofalseto restore the previous behavior. Structured element writes (PUT /pages/{id}) and the GSAP flag remain atedit_posts. Thescriptsendpoint already requiredmanage_options.
- Plugin version bumped to 1.0.1 (security audit class + route hardening).
- Plugin 1.0.2 hotfix — fatal
TypeErrorinclass-dynamic-tags.phpthat could take down the entire frontend. When an image element used a dynamic-data source inside a nested query loop, Bricks passed the full settings array (not a string) through thebricks/dynamic_data/render_tagandrender_contentfilters; both handlers calledstrpos()on it without a type check. Added an additiveis_string()guard on both call sites — no behavior change for valid string tags, the previously-fatal array case now passes through. Thebricks-api-bridge.zipon this release was rebuilt with the fix. (#3, reported + diagnosed by @sawka-tech.)
- Tool descriptions for
bricks_patch_page,bricks_append_elements, andbricks_build_pagenow explicitly advertise the plugin-side auto-backup guarantee that was previously documented only onbricks_update_page. All four destructive write operations create a backup before writing — enforced server-side, cannot be skipped from the MCP/LLM. No behavior change; closes a documentation gap. (h/t u/justinnealey for flagging it during the v1.0.1 launch discussion.)
- Validator allowlist expanded from 24 to 60 elements. Previously rejected:
text-link,list,svg,html,divider,alert,progress-bar,counter,countdown,breadcrumbs,search,social-icons,icon-box,audio,map,shortcode,logo,slider,lottie,nav-nested,offcanvas,toggle,sidebar,tabs,div, and 12post-*template elements. (h/t u/MysteryBros for flagging the missingtext-link.)
- Build-tool descriptions (
bricks_build_page,bricks_create_page,bricks_append_elements) now nudge the LLM toward theme-first workflow: fetchbricks_get_theme_stylesandbricks_list_global_classesbefore generating elements, prefersettings.style: "primary"on buttons over manual styling, usetext-linkfor links instead of styled text-basic. Same tools, sharper guidance.
- 100+ MCP tools for Bricks Builder
- Full page CRUD (list, get, update, patch, append, build, clone, search)
- Template management (CRUD, clone, import, search)
- Global CSS classes with BEM support
- Complete style system (colors, fonts, CSS variables, theme styles)
- Backup and snapshot management
- SEO tools (meta, schema, sitemap, redirects, link checking)
- WordPress content management (posts, categories, tags)
- Navigation menu management
- Section presets (list, instantiate, save)
- Media management (upload, list, edit)
- Multi-site support with runtime switching
- HTML to Bricks converter
- Batch operations (up to 20 per request)
- Per-page asset management (CSS/JS separation)
- Security hardening (rate limiting, enumeration protection)
- Responsive inference for automatic breakpoint generation