VhBuilder Logo 1.jpeg
Builder
  • Home
  • Features
  • Pricing
  • Roadmap
  • Forums
  • Docs
  • Marketplace
Join Alpha

Our Roadmap

Track what we’re building, what’s next, and share your ideas with the community.

Planned

Component Library

Save any element or section as a reusable component and drop it into any page with a single click.

Global Style Variables

Define site-wide CSS variables for colours, typography, and spacing — synced across all pages in real time.

Media Gallery Panel

Browse, upload and insert media directly from a floating gallery panel within the builder canvas.

Next

Responsive Breakpoint Preview

Switch between mobile, tablet, and desktop breakpoints inside the canvas with per-breakpoint CSS editing.

Gutenberg Block Integration

Edit Gutenberg blocks directly in VhBuilder — no switching between editors.

In Progress

Alpha Public Launch

Opening the builder to alpha subscribers — invite-based early access with direct feedback loop to the team.

Structure Panel Sync

Full bidirectional sync between the structure tree panel and the live HTML/CSS/JS code editors.

Feature Requests

Got an idea for a new feature? Submit it below.

Search first to avoid duplicates — if it exists, upvote it instead.

Every idea is manually reviewed before publication.

The most popular ideas are considered for our official roadmap.

Thanks! Your idea has been submitted and will appear here once it's been reviewed.
24 Sep 2026
v0.4.36

Release v0.4.36

Added

  • Ideas form submission defaults: vh-ideas-form.js now merges a JSON object from the form root's data-vh-ideas-defaults attribute into every submission's data, e.g. data-vh-ideas-defaults='{"status":"Submitted"}'. The Roadmap page's Ideas Board uses it so new feature requests land in the Road Map collection with status "Submitted". Submissions still arrive as drafts, and system fields such as the vote count are still stripped server-side.
24 Sep 2026
v0.4.35

Release v0.4.35

Added

  • Votes field type (system, read-only) in Collections: pick votes (system, read-only) as a field type to show each document's vote count in the Collections panel. It's locked to the upvotes key, shown read-only with a lock label in the document form, and can't be edited from the panel, the Raw JSON editor, or a JSON import. Document list rows now show ▲ n for voted documents.
  • Remove vote: DELETE /api/cms/documents/:id/upvote and DELETE /api/public-cms/:tenantHex/documents/:id/upvote. Clicking an upvote button again now removes the visitor's vote.
  • Real voted state on page load: GET /api/cms/my-votes?ids= and GET /api/public-cms/:tenantHex/my-votes?ids= return which of the given documents the current account has voted on. vh-upvote.js uses this instead of localStorage flags and clears the old flags.
  • Vote recount utility: POST /api/cms/collections/:id/recount-votes recomputes every count in a collection from cms_document_votes. It can't set an arbitrary number.
  • Rate limits: 30 vote actions per account per minute (voteLimiter), and 10 anonymous public document submissions per IP per hour (publicSubmitLimiter).
  • tests/ideaVotingTenant.test.js covers the voting and system-field guarantees end to end.

Fixed

  • Vote counts could be faked on published pages: StandaloneLoopResolver.js (server) and lib/dataProviders.js (canvas) spread a document's JSON dataafter the real upvotes column, so any upvotes key in the data won. That included one set in the Raw JSON editor or sent by an anonymous visitor through the public Ideas submission route. The real id and upvotes now always win.
  • Vote counts can no longer be set through generic document writes: cmsController.js strips system fields (upvotes, any Votes-type or system: true field) server-side from createDocument and updateDocument, for the builder route and the anonymous public route. Attempts are logged, and legacy upvotes keys already stored in document JSON are cleaned on the next save and hidden from responses. The schema endpoints normalise the Votes field so its system flag can't be removed.
  • Public voting always failed with 401: the /api/public-cms/:tenantHex/.../upvote route never ran authenticate, so req.user was always empty and every visitor was sent to the login page. The public vote routes now authenticate the visitor's own account token.
  • Voting is now only open on published documents; drafts (unmoderated submissions) return 409.
  • Vote counts are recomputed from cms_document_votes after every vote/unvote instead of +1, so concurrent requests can't make them drift.
  • Deleting a document or collection now also deletes its vote rows.
23 Sep 2026
v0.4.34

Release v0.4.34

Fixed

  • Standalone builder stuck in offline/local-storage mode: react-builder/src/lib/builderAPI.js's startup reachability probe checked GET /api/templates to decide whether the Node backend was available — that route was public when the probe was written, but the tenant-DB migration (57b848c2) put authenticate in front of it, so the probe always 401'd and the app silently fell back to offline mode regardless of login state. Probe now hits the still-public GET /api/health instead.
  • Every backend data call from the builder (listPages, listTemplates, custom components, global sections, AI chat, media/font uploads) sent no auth at all: builderAPI.js's hand-rolled fetch() client (separate from the axios instance used for login/session) never attached the access token or credentials — invisible while those routes were public, fatal once the tenant migration required auth on them. Added a scoped authHeaders() helper in builderAPI.js's own fetch call sites, plus a global window.fetch patch in axiosInstance.ts (limited to the backend origin) so any current and future plain-fetch() caller elsewhere in the app gets the Bearer token automatically.
  • Silent-refresh-on-mount could kill a valid session: AuthContext.tsx's mount effect called POST /auth/refresh directly; React 18 StrictMode's mount→cleanup→mount cycle could fire it twice with the same single-use refresh-token cookie, tripping the backend's reuse-detection and revoking the entire token family. The two invocations now share one in-flight refresh promise instead of issuing two requests.
  • Pre-existing local/dev pages had no data in the new per-tenant database: the tenant-DB migration provisions a tenant database for new signups but never had a path to migrate content that existed before it — pages, templates, layouts, menus, CMS collections/documents, etc. were still sitting in the legacy template-backend/templates.db SQLite file. Added template-backend/scripts/migrateLegacySqliteToTenant.js (usage: node scripts/migrateLegacySqliteToTenant.js <userId>), a one-off, idempotent, column-intersection copier from SQLite into a user's vhb_tenant_<hex> MySQL database.
  • @import CSS rules silently dropped in consolidated page/template CSS: regeneratePageCssFile() and the template-save CSS builder in template-backend/index.js concatenate framework/header/page/footer CSS and then prepend a reset block, so any @import (e.g. a page's own Google Font import) buried in one of those pieces ended up after other rules — invalid per the CSS spec, so browsers ignore it. Added hoistCssImports() to pull every @import to the very top of the final output, in original order.
  • "Preview" button opened an authentication-error JSON page instead of the live preview: Toolbar.jsx still built the old shared-admin-key preview URL (?key=...) from before the tenant migration; GET /api/preview/:mode/:pageId now requires real per-account JWT auth, which a plain new-tab navigation can't provide via headers. middleware/auth.js now also accepts the access token as a ?access_token= query param (scoped to this link-navigation case), and the Preview button passes the real current access token instead of the dead admin key.
  • Several Settings-panel form fields (Stock Image/AI provider API key inputs, AI model selects, icon library search/checkboxes, header/footer preview toggles) were missing id/name/label association, and password-type API key fields lacked autocomplete, triggering DevTools accessibility/autofill warnings.
9 Sep 2026
v0.4.33

Release v0.4.33

Fixed

  • <header>/<footer> blocks show "[empty]" in the native Gutenberg editor: inc/block-editor.js's vhbuilder/semantic-html block registration (both edit() and save()) checked its own hardcoded isContainer tag list to decide whether to render <InnerBlocks> — but that list was missing header and footer, unlike the equivalent list in class-vh-rest-api.php's reconstruct_html_from_blocks(). Any header/footer block fell through to the generic "everything else" branch, which shows a literal [empty] placeholder in the editor instead of its nested content, and would have saved with the content stripped if re-saved from Gutenberg directly. Added header/footer to both lists so they match the PHP-side set exactly.
9 Sep 2026
v0.4.32

Release v0.4.32

Fixed

  • Saved block content corrupted for every non-Administrator save: VH_HTML_To_Semantic_Blocks's leaf-element converters (convert_leaf_element(), convert_image_element(), and the loose-text-in-container wrapper) stored a metadata.originalHtml attribute containing raw HTML (e.g. <p>...</p>) directly inside each block's own JSON attributes — which sit inside an HTML comment (<!-- wp:vhbuilder/semantic-html {...} -->). WordPress's wp_kses (which sanitizes post_content on every save for any user without the unfiltered_html capability — every non-Administrator, i.e. every playground author account) has a known limitation where a raw < inside a comment's own text breaks its comment-boundary detection, HTML-entity-escaping the whole comment. The escaped comment then rendered as literal visible text on the page instead of being parsed as a block, and the content was lost from the builder's own re-read on the next load. metadata.originalHtml was confirmed dead data on the read side for every tag this affects (reconstruct_html_from_blocks() already rebuilds these purely from heading/paragraph/linkText/imageUrl etc.), so it's removed outright rather than escaped.
9 Sep 2026
v0.4.31

Release v0.4.31

Fixed

  • Builder content lost on reload: VH_HTML_To_Semantic_Blocks::convert_container_element() wraps loose text found directly inside a container tag (e.g. <header>some text</header> with no <p>/<h1> wrapper) into a synthetic paragraph block, but only ever set metadata.originalHtml on it — not attrs['paragraph']. reconstruct_html_from_blocks() rebuilds recognized leaf tags (p, h1-h6, a, etc.) purely from their dedicated attribute (paragraph, heading, linkText, ...) and ignores metadata.originalHtml for those tags, so the text silently vanished on the very next page load even though the save itself reported success. Now sets paragraph on the synthetic block too.
9 Sep 2026
v0.4.30

Release v0.4.30

Fixed

  • Playground save permission denied: the playground lockdown mu-plugin (Playground plugin/mu-vhbuilder-page-lockdown.php in vhbuilder-manager-plugin) strips edit_posts from managed playground (author-role) accounts and only restores it for requests whose own query string has vh=builder — which the builder's admin-ajax.php save/load calls never carry (they're plain POSTs with no query string). Added vhb_lockdown_is_assigned_builder_ajax_request() to also recognize vh_* admin-ajax actions targeting the user's assigned page, so saving now works for playground accounts, not just the initial page load.
  • Builder save "Cannot access before initialization" error: saveLoadActions.js's WordPress-sync step declared const blockMarkup = conversionData.data.block_markup inside the same block where the outer let blockMarkup (the semantic HTML to convert) was already referenced earlier — the inner const shadowed the outer variable for the whole block, so the earlier references hit the temporal dead zone. Renamed the inner variable to convertedBlockMarkup.
8 Sep 2026
v0.4.29

Release v0.4.29

Added

  • Branded 404 page for the template-backend API (render404Page()), using the real brand system from brand_assets/ — Bebas Neue/DM Sans/JetBrains Mono, the orange gradient logo mark, dark theme.

Fixed

  • build-vhbuilder.ps1's backend and marketplace output directories were only cleaned when -Clean was explicitly passed, so stale files from old builds silently accumulated across every release. Now always cleaned first.
  • The API's 404 handling only ever covered single-segment paths (via the existing /:slug? catch-all); multi-segment paths (e.g. /webhooks/legacy-import) fell through to Express's bare default 404. Added a final catch-all so every non-/api/* path gets a real response; /api/*'s existing JSON 404 is unchanged.
7 Sep 2026
v0.4.28

Release v0.4.28

Fixed

  • FTP deploy duplicate-directory bug: a relative remote_path was re-resolved against wherever the previous file's upload left the connection, nesting a duplicate copy of the target folder on every deploy. Now resolved to an absolute path once per connection.
  • Failed deploys were logged with provider "unknown" instead of the real provider (ftp, sftp, etc.).
  • Deploy Settings now auto-loads the most recently used saved config instead of resetting to a blank form on open, and Test Connection can reuse a saved config's secret by name instead of requiring the password to be re-entered.
  • Re-importing a site via the new Import Site feature (below) would have created duplicate pages on every run — pages are now matched by slug and updated in place.
  • build-vhbuilder.ps1 was shipping dev/test/backup artifacts (*test*, *.bak, *.backup, react-builder/scratch/) into the production theme package; the build now excludes them.

Added

  • Import Existing Site: pull a saved FTP/SFTP deploy target's live files and create pages/templates from them, for connecting to a site that already has content.
  • Warning banner in Output Settings when the Partials output format is selected, clarifying it ships unresolved {{include:header}}/{{include:footer}} tokens rather than rendered HTML.
7 Sep 2026
v0.4.27

Release v0.4.27

Added

  • Canvas Drag-and-Drop: Full drag-and-drop support allowing users to drag elements from the Elements panel and custom user elements directly onto the canvas.
  • Glowing Placement Indicators: Dynamic glowing orange insertion line between existing elements (horizontal for block, vertical for row flex layouts).
  • Empty Container Drop Targeting: In-editor support for empty sections, containers, blocks, and plain divs with an 80px drop surface and centered "DROP INSIDE" badge, allowing direct dropping into newly created sections and empty container wrappers.
  • Toolbar Elements Toggle Button: Added a plus (+) button to the top toolbar next to the brand divider with glowing orange hover styling to toggle the Elements panel.
  • Pages Folders Admin: Added native WordPress admin folder management for pages with custom script and style enqueuing.

Changed

  • Store actions insertElementAt, insertElementAtTarget, and insertElementInstance enhanced with targeted positioning (before, after, inside).
  • In-editor helper styles dynamically mark empty containers with data-vh-empty="true" to preserve visible hover surface.
  • Double-safety in elementActions.js ensuring drops inside sections target inner .container wrappers.
9 Aug 2026
v0.4.26

Release v0.4.26

Changed

  • Fix Icon Picker search and prevent Element Creator closure on SVG upload
9 Aug 2026
v0.4.25

Release v0.4.25

Changed

  • Fix Framework Panel CSS setter
9 Aug 2026
v0.4.24

Release v0.4.24

Changed

  • Add Edit Master option to Structure Panel
9 Aug 2026
v0.4.23

Release v0.4.23

Changed

  • Add CSS Cleanup admin page and styling improvements
8 Aug 2026
v0.4.22

Release v0.4.22

Added

  • Icon Picker Panel: Reimplemented the Icon Picker as a proper Builder side-panel instead of a modal, fully integrating with the new layout.
  • SVG Upload Integration: Added the ability to upload and insert custom SVGs directly via the Media Gallery from within the Icon Picker.
  • Settings Icons Card: Separated settings icons selection logic into its own component for better modularity.
8 Aug 2026
v0.4.21

Release v0.4.21

Added

  • Design Board Infinite Canvas: Added infinite canvas workspace, refactored page frames and zoom controls.
  • Framework Improvements: Code editor soft-wrap toggle, sidebar behavior updates, and structural layout improvements.
25 Jul 2026
v0.4.20

Release v0.4.20

Added

  • Form Builder (TODO #60): drag/click-to-insert form element with 9 field types (text, email, select, checkbox, textarea, file, number, date, hidden), full parity between the standalone Node backend and embedded WordPress. New data-vh-form-builder widget (FormBuilderWidgetEditor.jsx + FormFieldConfigurator.jsx) with form-level settings (target email, target Collection, messages, redirect URL, honeypot, submit label) and a reorderable field list (@dnd-kit, per-field validation rules, email confirmation-field pairing). Submission handling is both email notification (nodemailer in Node, wp_mail() — the theme's first use — in WordPress) and Collection document storage, mandatory per spec; each field can be mapped to a specific Collection schema field key via a new per-field "Collection field" dropdown, populated from whichever Collection is selected as the submission target, falling back to the field's own internal id when unmapped. No new database table — the page's own rendered HTML is the only source of truth for field/validation rules (no DB record of "what a form looks like" exists), so the client reads them off the DOM at submit time and the server re-validates server-side rather than trusting the client's checkValidity(). New public, rate-limited (20/hour/IP) endpoints: POST /api/forms/:formId/submit (Node) and POST /vhbuilder/v1/forms/{form_id}/submit (WordPress, its first genuinely public REST route). File uploads use magic-byte signature detection (not client-supplied mimetype/filename) and randomized filenames in both backends. Hand-synced runtime pair (assets/js/vh-form-runtime.js + VH_FORM_RUNTIME_JS in Canvas.jsx) drives client-side validation, submission, and success/error messaging. Static site exports now also get the form runtime inlined directly into the page (a gap that also affects Gallery/upvote/ideas-form but was only fixed for forms in this pass).

Fixed

  • Canvas click handler silently blocked native form-control interaction: useCanvasEventHandlers.js's capture-phase handleClick unconditionally called preventDefault()/stopPropagation() on every canvas click, which ate typing, checkbox toggling, <select> opening, and submit-button clicks for every form (not just the new Form Builder — the pre-existing plain "Form" element too). Added a scoped bypass for input/select/textarea/label/submit button inside [data-vh-form-builder], ordered after the existing locked-element check.
  • Toggle switches were unstyled across every widget editor: .vh-toggle-switch/.vh-toggle-slider were referenced by 18 files (Link/Image/Video/Gallery/Form/FormBuilder widget editors) but never actually defined anywhere in the codebase, so every toggle in every widget settings panel rendered as a bare native checkbox instead of the intended switch UI. Fixed once in EnhancedStylePanel.css, benefiting every widget editor that uses the class, not just Form Builder.
  • Form Builder inputs used builder-chrome dark-theme tokens as page CSS: the default inserted styling used var(--vh-bg-elevated, #1a1a1a)/var(--vh-border, #333) — tokens meant for the builder's own dark UI, undefined on real pages — so text inputs rendered as a near-invisible black box on real/published pages. Replaced with plain page-appropriate colors.
  • Form field CSS used a compound descendant selector, breaking custom-class overrides: the default styling targeted .vh-form-field input (specificity: class + element), which always beat a single user-added class at equal-or-lower specificity regardless of source order — so adding a class via the Style panel and setting a background/border had no visible effect without !important. Replaced with a single flat .vh-form-control class applied directly to each control, matching the specificity of any user-added class so the normal "add a selector, style it" workflow works.
  • Backend rejected same-origin requests with a CORS 500: this Node backend serves its own pages (live-sync preview, published pages) whose client-side scripts (vh-form-runtime.js, and pre-existing vh-ideas-form.js/vh-upvote.js) fetch back to the same server — browsers still send an Origin header on those requests even though they're same-origin, but the backend's own origin (http://localhost:${PORT}) was never in its own CORS allowlist, so the cors() middleware threw and Express returned a 500 for every such request. Added the backend's own origin (both localhost and 127.0.0.1) to allowedOrigins.
24 Jul 2026
v0.4.19

Release v0.4.19

Added

  • Client Handoff Mode (TODO #64): a locked-down view for clients, toggled via a new lock-icon button in the toolbar (persisted to localStorage, with a warning banner while active). While enabled: the Structure Panel, HTML/CSS/JS editors, and AI Assistant are hidden and can't be reopened (via their sidebar buttons, keyboard shortcuts, or canvas right-click) since togglePanel() itself now refuses to open any of them while handoff mode is on; the "Add Element" insert strip is hidden and its Ctrl+Shift+A shortcut disabled; the Style Panel is restricted to its Content tab only. On the Content tab, TextWidgetEditor/HeadingWidgetEditor/LinkWidgetEditor are pared down to just text/label editing plus new Colour and Font Size controls (a link's destination stays off-limits — that's a navigation change, not content), ImageWidgetEditor keeps only "Replace Image", and Video/Navigation/Layout/Form widgets plus component-instance properties are locked out entirely with a plain "not editable" message rather than trying to prune each one's many fields.
24 Jul 2026
v0.4.18

Release v0.4.18

Added

  • Gradient builder (visual) (TODO #46): GradientSection.jsx rebuilt into a full visual gradient editor — linear/radial/conic type toggle, a draggable colour-stop bar (click to add, drag to reposition, double-click to remove), an angle wheel for linear/conic, centre X/Y for radial/conic, and a live preview swatch. New GradientUtils.js (parseGradient/buildGradient) and a shared utils/splitTopLevelCommas.js (extracted out of BoxShadowUtils.js, since both need the same "split on commas but not inside rgba(...)" logic).

Fixed

  • Gradient type switching (Radial → Linear/Conic) no longer resets the angle to a meaningless 0° — only resets when the previous type was radial, since radial has no angle of its own.
24 Jul 2026
v0.4.17

Release v0.4.17

Added

  • Natural language page generation (TODO #35): the AI Assistant can now generate pages from a Collection + Template directly from a chat request (e.g. "Generate a team page for each person in my Team Members collection using the team-member template"), with no button click required. The AI is prompted to reply with a fenced vh-action JSON directive for this specific intent; the app parses and executes it via a new generatePagesFromDirective() utility (name-based Collection/Template resolution over the existing generatePagesForDocuments() engine from #24), then shows an inline success/error result card in the chat instead of raw JSON.

Fixed

  • AI Assistant sometimes wrote HTML/CSS instead of following the vh-action directive: every chat message auto-attaches a canvas screenshot, and the system prompt's "build pixel-perfect from an image" rule competed with the new directive rule for page generation requests — the same prompt text could produce either outcome depending on the AI's response. Reworded the screenshot context to be explicitly ambient (not a build target) unless the user's own text asks to replicate a design, and marked the page-generation rule as taking priority. Verified fixed on both Anthropic and Gemini.
24 Jul 2026
v0.4.16

Release v0.4.16

Added

  • Pages folders: pages can now be grouped into folders, mirroring the Collections panel's folder pattern. Also added natively to wp-admin's Pages list (edit.php?post_type=page) — a sidebar with drag-and-drop, a "Folder" column, and query filtering, following the same precedent set by the Media Library folders admin integration. Stored as _vh_page_folder post meta.
24 Jul 2026
v0.4.15

Release v0.4.15

Added

  • Dynamic Pages / Collection-driven page generation (TODO #20–#34, #36 — the full "Collection-Driven Pages" feature epic):
    • Template/layout scope now supports {{field}} tokens bound to a Collection, with a Collection picker and schema-field autocomplete in the HTML editor and Style Panel (#20), plus live template preview against real document data with a document switcher (#21/#22).
    • "Generate from Collection" button in the Pages panel: pick an existing Collection + page Template, preview a sample of titles/slugs, then generate one Page per document (#24/#25), skipping pages that already exist unless overwrite is requested.
    • "Import & Generate" wizard: upload a .json file, create/choose a Collection to import into, create/choose a page Template, set a slug pattern ({{field}} tokens, validated for uniqueness) and publish/overwrite options, then generate everything in one operation (#28/#29). New "Ask AI to build this template" step hands the Collection's schema + sample records to the AI panel to draft the template (#30).
    • Optional listing/index page generation alongside per-document pages, reusing the existing loop system (#31); {{prev_page_url}}/{{next_page_url}}/{{prev_title}}/{{next_title}} tokens resolved from document order (#32); sitemap.xml now generated as part of every deploy/preview and downloadable on demand (#33).
    • Incremental regeneration: a "Regenerate" button on page-generating Templates re-resolves only pages whose source document changed since last generation, skipping manually-edited pages unless forced (#26). Generated pages store their source Collection/Template/document and show a "Source" badge linking back to the originating document (#27).
    • "→ Collection" button on AI-generated JSON code blocks in the AI Assistant chat, and Collections' own JSON import, for turning AI-drafted or hand-authored JSON straight into a Collection without manual copy/paste (#34/#36).

Fixed

  • B24 — isWpMode check always evaluated true, permanently hiding standalone-only UI ("Import Site", Marketplace remote sync, Licence nav item) in every deployment. PagesPanel.jsx, TemplatesPanel.jsx, and BuilderNavigation.jsx computed isWpMode from config?.ajaxUrl, but the standalone dev-mode fallback config also sets a placeholder ajaxUrl, so it was never false. Now checks config.nonce !== 'dev-mode' instead, matching the existing WP block-sync check.
23 Jul 2026
v0.4.14

Release v0.4.14

Fixed

  • Broken build script: build-vhbuilder.ps1 referenced undefined variables ($BUILD_DIR, $BUILD_OUTPUT_DIR, $RELEASE_ZIP_DIR) left over from a variable rename in v0.4.11, so every copy/zip step failed with Join-Path/Test-Path errors. Restored consistency with the current $THEME_DIST_DIR/$THEME_OUT_DIR names.
  • Absolute localhost URLs baked into uploaded media/fonts: template-backend/index.js had 6 upload/optimize/download code paths that stored http://localhost:${PORT}/uploads/... as an absolute URL instead of a relative path, breaking media and custom fonts once deployed (Mixed Content errors in production once the standalone builder is served over HTTPS). Now consistently relative, matching the pattern already used elsewhere in the file. Does not retroactively fix URLs already stored from before this fix.
  • Standalone builder SPA routes 404 on direct load/refresh: /builder, /login, etc. are client-side React Router routes with no matching file on the static host serving builder.vhbuilder.online, so a direct hit or page refresh 404'd. Added react-builder/public/.htaccess with an SPA fallback rewrite to index.html.
  • Element auto-mapper loop data collisions: loop data lookups used the bare data-vh-loop key, so two loops sharing the same default name ("new_loop") but different configs could read each other's data. Now keyed by ${loopKey}::${configStr}, matching how useCanvasLoopData.js/loopRenderer.js already cache it.
  • Duplicate notification ids: notify() used Date.now() alone as the id, causing React duplicate-key warnings when two notifications fired in the same millisecond. Added a per-call counter suffix.
  • Collections loadDocuments() race condition: overlapping requests for the same collection (e.g. the panel's reactive selection effect racing an explicit post-publish reload) could let a stale response overwrite a newer one. Now tracks the latest issued request per collection and discards stale results.
  • Collections publish matching false positives: publishing a document could replace every item in the list instead of just the target, because two documents with an empty item_key/document_key were treated as matching. Now only matches when both sides have a non-empty value.
  • Canvas loop token rendering: the canvas preview wasn't resolving {{loop}} tokens before building body content (missing renderLoops() call).
  • Reverted package.json and block.json, which had been silently overwritten with unrelated content (react-builder/package.json and inc/block.json respectively) by the build script bug above, plus deleted ~130 stray duplicate files it had flat-copied into the theme root.

Added

  • Collections "autoincrement" field type: auto-assigns the next sequential value on document creation, with a manual "backfill" action for existing documents missing a value.
  • Collections "icon" field type: new Icon field backed by IconPickerModal, wired into the Enhanced Style Panel's content editor (reads/writes data-icon) and rendered on the front end via a newly-enqueued Iconify runtime script; a Font Awesome stylesheet is also now enqueued for the legacy icon-font convention. Both the WordPress live-render path (functions.php) and the static-export path (deployBuilder.js) ship the same two includes.

Changed

  • Rebuilt the template-backend "Features" static page stylesheet (template-backend/public/css/pages/features.css) and added a new test.css page stylesheet alongside it.
22 Jul 2026
v0.4.13

Release v0.4.13

Fixed

  • Template Collection Binding Persistence: Fixed a bug where binding a collection to a template in the Template Settings panel was erased when saving the canvas content.
  • Code Editor Autocomplete: Fixed Monaco Code Editor failing to display {{ context-aware autocompletion for collection schema fields by adding an explicit document change listener and fixing a lifecycle bug where extensions did not reload on collection binding changes.
21 Jul 2026
v0.4.12

Release v0.4.12

Changed

  • Refreshed stale process documentation: .github/ai-instructions.md, .github/docs/features/overview.md, and .github/docs/architecture/overview.md all still described the codebase as of v0.3.3 (wrong component list, a "Future Enhancements"/"Next Phase" list of already-shipped items, and a version-sync reference to a react-builder/dist/version.json file that doesn't exist — the real third sync file is functions.php's VH_VERSION constant). Rewrote all three against the actual current codebase and CHANGELOG.md/TODO.md history. Also fixed the same stale version.json reference in .github/COMMIT_CHECKLIST.md and made updating these docs an explicit pre-commit step instead of an easy-to-skip "(optional)" note.
21 Jul 2026
v0.4.11

Release v0.4.11

Added

  • Scroll-to-section navigation: right-click any section/article/div/main and "Set as Section Anchor" to give it an id; a new "Page Sections" list in the Structure Panel shows every anchor on the page with jump-to and copy-link actions, and "Insert Nav" auto-generates a <nav class="vh-section-nav"> linking all of them. Ships scroll-behavior: smooth into the page's own CSS the first time an anchor is set, so links scroll smoothly with no runtime JS, in the builder canvas and on the deployed site alike.
  • Global sections / synced blocks (standalone/Node backend): save any Structure Panel element as a reusable section (data-vh-global-section-id); a new Global Sections panel lists definitions with Insert/Edit/Unlink/Delete, and editing a synced instance propagates the change to every other page carrying the same section via node-html-parser-based sync (not regex, avoiding the text-matching pitfalls documented for Gutenberg sync in v0.4.09/0.4.10).
  • Media library tagging & folders: every media item can carry tags and a nested folder path, with drag-and-drop between folders, bulk tag/move actions, and a matching folder tree inside native WordPress admin's Media Library (upload.php) so both surfaces read/write the same metadata.
  • Multi-select elements: Shift/Ctrl-click in the Canvas or Structure Panel selects multiple elements at once, with a floating toolbar for delete-all, group-in-div, six-direction alignment, and pasting styles onto every selected element.
  • Git-style diff view: a dependency-free line-by-line diff panel, opened from the Toolbar, compares the current HTML/CSS/JS against the last loaded/saved snapshot, with collapsible unchanged-line runs and a "Revert All Changes" action.
  • Shape dividers: 12 SVG presets (waves/angled/curves/geometric) applied to the top/bottom edge of a section, article, div, or main, with flip/colour/height/layering controls in the Style Panel and a one-click "Add Shape Divider" default from the Structure Panel's context menu.
15 Jul 2026
v0.4.10

Release v0.4.10

Added

  • CSS Output Inspector: new "Inspect" tab in the Style Panel (Ctrl+Shift+I) — merges Framework CSS, page CSS, and inline styles for the selected element, scores each declaration's specificity, marks overridden declarations, and click-to-jumps into the CSS editor.
  • HTML validation panel: new "Validation" tab in the Settings Dashboard — flags invalid nesting, unclosed tags, deprecated tags, missing required attributes, and duplicate IDs, with inline Structure Panel indicators and a site-wide or single-page scan (Ctrl+Shift+L).
  • Accessibility checker: new "Accessibility" tab in the Settings Dashboard — WCAG-style checks for alt text, heading hierarchy, link text, form labels, ARIA usage, and colour contrast, with one-click fixes and an "Ask AI to fix all errors" hand-off to the AI panel.
  • Performance dashboard: new "Performance" tab in the Settings Dashboard — page-weight, image, CSS-health, and HTML-health checks with a 0–100 score and one-click fixes (missing alt, missing width/height, strip !important, minify CSS).
  • Inline SEO panel: Page Settings gained canonical URL/noindex/nofollow, Open Graph, Twitter Card, and Schema.org fields with character counters and a live Google SERP preview, output through the existing social-meta system in both WordPress and standalone/deploy modes.
  • Pseudo-class & pseudo-element styling: a state selector (Normal/:hover/:focus/:active/::before/::after/more) above the Style tab scopes every style control to a native-nested &:state { } block, with live canvas preview for interactive states.
  • Visual position controls: Sticky/Relative/Absolute/Fixed now show Top/Right/Bottom/Left offsets and Z-Index inline in the Settings tab.
  • Visual box-shadow builder: multi-layer shadow editor (offset/blur/spread/colour/inset, add/remove layers, live preview) replacing the plain box-shadow text field.
  • Slider controls for Transform: Translate/Rotate/Scale/Skew now have range-slider + number-input pairs, with independent scaleX/scaleY.
  • Animation/motion system: 19 scroll/load/hover-triggered entry animation presets with duration/delay/easing/repeat controls, driven by an IntersectionObserver runtime in the canvas.
  • Conditional display: six condition types (device, login state, URL parameter, time of day, page type, body class) with AND/OR logic, live on the published frontend, plus a canvas device-preview toggle.
  • Custom font upload: upload .woff2/.woff/.ttf/.otf, add a Google Font by name, or add by direct URL — usable from the Framework Typography step and the Style Panel's font pills, rendering live in the canvas and app shell.
  • Framework token swatches: colour/font/spacing tokens parsed from Framework CSS now appear as clickable swatches in every colour input and the typography font picker.
  • Copy/paste styles between elements (Ctrl+Shift+C/Ctrl+Shift+V) and element locking (blocks select/move/delete/duplicate on locked elements, with a Structure Panel lock icon and canvas outline).
  • Find & Replace (Ctrl+F/Ctrl+H): search/replace across HTML, CSS, and JS with canvas and Structure Panel match highlighting.
  • Deploy system overhaul (standalone/Node backend): configurable output settings (flat/partials, filename pattern, framework CSS inline/shared, asset paths, minify, base URL), a dry-run deploy preview, hash-based incremental deploy, and a ZIP "Import Site" flow that auto-detects VHBuilder/partials/flat-HTML formats.

Fixed

  • Gutenberg block sync silently stripped builder attributes and discarded Gutenberg-side edits (WP mode): a cleanup regex in the real save path stripped every data-vh-* attribute except loop ones before block conversion, wp_update_post()'s internal wp_kses pass stripped survivors a second time, and semantic leaf blocks (heading/paragraph/link/image) were rebuilt from a frozen originalHtml snapshot instead of the block's live attributes — so edits made directly in Gutenberg never made it back into the builder. Added a post-save sync-health check that warns when attribute survival drops below 80%.
  • Deploy output was always written as index.html regardless of page slug — filenames now derive from the slug (or [slug]/index.html in pretty-URL mode), with only the homepage deploying as index.html.
  • SEO metadata could be silently blanked on save in standalone/localStorage modes — the save payload only read SEO fields while the settings modal was open, with no fallback to the last-loaded page state; the standalone backend's PATCH /api/pages/:id also silently dropped title.

Changed

  • Performance dashboard moved from a standalone slide-in panel into its own tab inside the Settings Dashboard, alongside Accessibility/Validation/Overview.
  • Position controls consolidated into the Settings tab, removing a duplicate Style-tab "Position" section from an earlier pass.
6 Jul 2026
v0.4.09

Release v0.4.09

Added

  • Page revision history UI: a "Version History" slide-in panel (RevisionsPanel) surfaces past saves with relative timestamps, change summaries, and a restore flow with inline confirmation (no window.confirm). Wired into the Toolbar (history icon) and Page Settings panel ("View history" link). Works across all three adapters: WordPress mode (VH_Revisions + REST endpoints), the standalone Node backend (new page_revisions SQLite table, capped at 50 per page), and offline/localStorage mode (capped at 10 per page).
  • Builder capabilities system: granular vh_use_builder / vh_edit_templates / vh_edit_framework / vh_manage_marketplace / vh_manage_elements capabilities (VH_Capabilities), mapped onto administrator/editor/author roles. REST permission checks now go through these instead of blanket edit_posts/manage_options, and the Marketplace tab / Framework entry hide for roles that lack them.
  • Sanitization hardening: vh_allowed_html() extends wp_kses_allowed_html('post') with a data-* wildcard so data-vh-* builder attributes survive sanitization on every builder save path.
  • Template inheritance: templates can embed {{include:TYPE}} tokens to pull in another template's rendered HTML/CSS, resolved recursively with circular-include guards; the canvas renders included templates as a non-editable chrome overlay with an "Edit {Type}" shortcut.
  • Standalone licensing: lightweight licence-key infrastructure for the Node backend (validate/status/deactivate endpoints, VH_LICENCE_KEY env var, a Settings → Licence tab, and a non-blocking "unlicensed" banner). WordPress mode is untouched — it keeps its existing subscription-linked licensing.
  • Remote template sync: standalone-mode template feed sources with a "Sync" tab on the Templates panel — install or update templates from a configured feed, with an update-available count badge on the sidebar nav item.
  • Code export: export the current page as standalone HTML, or the whole site as a ZIP, with options to minify, inline vs. separate the framework CSS, and resolve {{tokens}}. Also available per-page from the Pages panel.
  • Collections folder grouping: collections can be grouped into sidebar folders via drag-and-drop or a "+ New Folder" button, with inline rename/delete.

Fixed

  • Crash creating a component from the Structure Panel: handleCreateComponent() passed a DOM Element where getDefaultBemTitle() expected a tag-name string, crashing on tagName.toLowerCase() and blocking "Create Component" entirely. Fixed the call site and added defensive type guards to getDefaultBemTitle()/generateBemClasses().
  • Revisions were never actually being recorded in WordPress mode: the builder's real save path (vh_save_content) never called VH_Revisions::save_revision() — only a separate, unused REST endpoint did, so the new Version History panel would otherwise have stayed permanently empty. Wired the revision-save call into the actual save path.

Changed

  • Migrated component stylesheets to the shared --vh-* design tokens for consistent theming across light/dark mode.
  • Minor UI polish: form submit-on-Enter fixes in the AI settings cards, refreshed Radix icons in the Structure Panel tree, small wording/markup tidy-ups.
  • Skips the silent auth-refresh network call on public auth pages (login/register/password reset/etc.) unless a prior session hint suggests the user was already logged in; adopted React Router v7 future flags.
3 Jul 2026
v0.4.08

Release v0.4.08

Added

  • Roadmap / Ideas Board / Changelog system: A full Canny-style public feedback board, built entirely on the existing standalone Collections CMS rather than as a one-off feature.
    • New elements: Roadmap Column (a single kanban-style column, duplicated per status and bound to a Collection filtered by field), Ideas Board (public submission form + upvote-sorted list), Changelog List, and Changelog Detail (a single-document detail view).
    • Upvoting: POST /api/cms/documents/:id/upvote, gated by the existing subscriber JWT auth, with a cms_document_votes dedupe table (one vote per user per document) and an atomic SQL increment. Upvote counts are a dedicated column — never reachable through the generic document-patch endpoint, so they can't be tampered with via a crafted request.
    • Moderation: reuses the Collections system's existing draft/publish flow as-is — submitted ideas land as drafts and only appear publicly once manually published.
    • Single-document detail pages: any Loop's "Filter value" can now be the literal token {{url:paramName}}, resolved against the current page's own query string at render time (both canvas preview and published pages). This is generic, reusable infrastructure — not specific to the changelog.
    • Query Builder gained Filter by field / Filter value / Sort by / Sort direction controls, backed by additive filterField/filterValue/sortBy/sortDir support in both the client-side provider and its server-side twin.
    • Collections schema gained a real select field type (comma-separated options), rendered as a dropdown in the schema editor, the document editor, and the Query Builder's filter-value field — replacing free-typed status values that were prone to typo mismatches.
    • Imported all 25 historical versions from CHANGELOG.md into the Changelog collection as condensed public summaries, each linking to a full-detail page.
  • Tabs element rewritten as pure CSS: no JavaScript at all — a hidden radio input per tab drives panel visibility via :has(), matched by position. Moved out of the Components registry into the Elements library's "General" category (removing two broken legacy button-based Tabs entries that had no CSS or JS at all), using an Iconify icon (iconoir:window-tabs) via the existing @iconify/react dependency.

Fixed

  • Collections/Loop rendering was broken outside WordPress mode: VHCollectionsProvider had no fallback for the standalone Node backend and always hit a WordPress-only REST path; StandaloneLoopResolver had no case for vh_collections loops at all, so any Collection-bound content silently rendered empty on published pages.
  • fetchCollectionDocs applied its row LIMIT before filtering, so a filtered query (e.g. a single-document detail page with limit: 1) only ever checked the single most-recently-created row in the whole collection. LIMIT is now applied as a display cap after filter/sort.
  • Canvas loop data collision: useCanvasLoopData/loopRenderer keyed resolved data by the loop's (often-duplicated default) name alone, so multiple loops sharing a name — e.g. several Roadmap columns — silently overwrote each other's data in the canvas preview. Now keyed by name and the loop's own config, so same-named loops with different bindings no longer collide.
  • Text fields not reflecting canvas content: updateElementText wrote via element.innerText on a detached, unrendered DOMParser document, where innerText's setter is unreliable; switched to textContent to match the read path. Separately, the two places that build a fresh element-selection snapshot never captured textContent at all, so the Text widget's Content field always started blank on a fresh selection or insert.
  • CSS editor selector matching rewritten: replaced naive substring search with real selector-structure parsing (:has()/:not() contents and ancestor segments in a descendant chain are now correctly excluded from "what does this rule actually style"). Also fixed a related bug where the matcher was called with a trailing " {" from the rule-iteration helper, which the new structural parser initially mishandled.
  • CSS focus-mode editing could grow the stylesheet on every edit: when a focused selector matched two or more rules with unrelated rules interleaved between them in the source (e.g. .tab-btn), a one-way "found match" flag caused the interleaved content to be shoved to the end of the stylesheet on every edit instead of staying in place — a feedback loop that added a spurious blank line per edit. Fixed by tracking the actual gaps between matches and re-interleaving edited content back into them.
1 Jul 2026
v0.4.07

Release v0.4.07

Added

  • Dynamic Nav Menu Synchronization: The Nav element now syncs with WordPress menus and Builder menus dynamically, keeping navigation in step with CMS-managed menu structures without manual rebuilds.

Fixed

  • CORS for New Subdomains: Added builder.vhbuilder.online and marketplace.vhbuilder.online to the allowed-origin lists in both the WordPress REST API (class-vh-rest-api.php) and the standalone backend (template-backend/index.js). A wildcard pattern (*.vhbuilder.online) is also accepted to cover future subdomains.
  • Production API URL: Corrected VITE_BACKEND_URL in .env.production to point at api.vhbuilder.online instead of the root domain, aligning it with VITE_AUTH_API_URL and removing a mismatch that caused request failures on the deployment server.
  • Template Backend Framework CSS: Replaced the framework CSS stub with the full VH Framework v1.0.0 stylesheet, restoring correct base styles on the standalone builder site.
25 Jun 2026
v0.4.06

Release v0.4.06

Added

  • Universal Link Wrapper Thumbnail Preview: Re-implemented and styled thumbnail previews inside the LinkWrapperControl for elements utilizing the Lightbox Image option, pulling the live image directly under the URL. Also implemented thumbnail preview inside the ImageWidgetEditor.

Fixed

  • Missing Group Tags in Widget Editors: Fixed a syntax bug introduced during UI grouping where closing </div> tags were missing in VideoWidgetEditor, FormWidgetEditor, and LinkWidgetEditor.
  • Property Panel Scroll & Flexbox: Fixed a classic flexbox bug where the vh-style-panel-content container failed to scroll vertically because it lacked min-height: 0. It now correctly stops at the window's edge and provides a scrollbar.
  • Header Padding Condensation: Greatly reduced redundant double-padding and inline margins throughout the EnhancedStylePanel header, title row, and tabs, restoring significant vertical real estate to the property editor area.
25 Jun 2026
v0.4.05

Release v0.4.05

Fixed

  • CSS Editor Duplication: Fixed a bug where typing invalid CSS inside focus mode would break the parser and cause CSS blocks to duplicate. updateFocusedCss now preserves the exact block position (prefix and suffix) instead of separating all focused/non-focused CSS.
  • CSS Cascade Preservation: Focus mode edits now perform in-place replacement, guaranteeing that the cascade order of your original global stylesheet is preserved.

Added

  • CSS Syntax Linter: Added @codemirror/lint to the CSS editor. Malformed code, unclosed braces, or incomplete statements (like trailing @keyframes) will now trigger a red wavy underline and display an error icon in the editor gutter.
21 Jun 2026
v0.4.04

Release v0.4.04

Added

  • AI Assistant Chat Interface Upgrades:
    • Implemented dynamic provider icons (e.g. SiClaude for Anthropic, SiGooglegemini for Google) directly in the chat bubbles to visually confirm the selected AI model.
    • Linked the chat interface's user avatar to the authenticated VHBuilder profile photo via useOptionalAuth and resolveAuthUrl.

Fixed

  • AI Models Legacy Fallbacks: Added a backend interception in aiController.js to forcibly upgrade deprecated/cached Claude 3.5 and Gemini 1.x/2.x model strings sent by the frontend, seamlessly mapping them to their modern claude-sonnet-4-6 and gemini-3.5-flash counterparts to prevent connection API errors.
  • AI Typing Indicator Alignment: Moved the typing indicator to render directly inside the active assistant message bubble rather than floating in a separate isolated container, eliminating empty space glitches.
9 Jun 2026
v0.4.03

Release v0.4.03

Added

  • CSS Resets Section: Created a standalone CSS Resets panel under Theme Fundamentals, situated between General and Colors, letting users customize base rules.
  • WordPress Integration: Updated vh_save_framework() in functions.php to write global.css to the assets cache directory, and enqueued it via VH_Style_Loader for frontend pages and the block editor canvas.
  • Standalone Node Backend Integration: Updated POST /api/framework in the standalone backend to save global.css to public/css/global.css, and injected the stylesheet link tag in the rendered page HTML template.
  • Test Suite Enhancements: Added automated integration test suite in tests/global_css.test.js verifying the framework saving and stylesheet rendering pipelines. Added test environment check to prevent server port binding conflicts under Jest.
  • Element Layout Properties: Added display, direction (flex-direction), align main axis (justify-content), align cross axis (align-items), width, min-width, max-width, column gap, and row gap to each of the 32 theme elements.
  • Accordion Ordering: Reordered the new layout options to the very top of each element editor panel, followed by a new "Styles" header for properties like colors, borders, padding, and margin.

Fixed

  • CSS Synchronization & Reset Clearing: Enhanced handleElementsChange to dynamically write and update style/layout properties inside :root in the global.css stylesheet. Added a robust parent-reset detection mechanism that strips all of an element's variables from the stylesheet when its parent accordion is reset.
  • Stylesheet Auto-Creation: Enabled auto-initialization for global.css in all property handlers to prevent silent synchronization failures when custom stylesheets are empty or missing.
9 Jun 2026
v0.4.02

Release v0.4.02

Fixed

  • Aligned Layout Margins: Standardized the margins of all major editor panels (like Typography, Colors, Elements, and Conditions accordions) to a unified 12-pixel layout to match the General section wrapper's margins.
  • Nested Accordion Styling: Wrapped nested accordions (like the sub-accordions under the BlockQuote control) with a new wrapper to allow for customized styling, including a 6px 0 margin, compact 8px 12px header padding, and 10px 0 body padding to prevent double margin nesting.
  • Removed Duplicate CSS: Cleaned up duplicated .condition-body declarations from ConditionsEditor.css to consolidate styles.
  • OKLCH Color Picker Spacing: Corrected the OKLCH picker alignment and spacing constraints.
7 Jun 2026
v0.4.00

Release v0.4.00

Fixed

  • Framework Fundamentals Layout Overflow: Fixed an issue where opening the Colors accordion pushed the back border underneath the preview. Implemented strict flexbox constraints (max-height: 100%, min-height: 0, and overflow: hidden) on the .fundamentals-step-v3 container to force inner scrolling. Increased the left sidebar width specifically for the Fundamentals step to 400px to naturally accommodate the wide OKLCH color picker without layout shifting.
7 Jun 2026
v0.3.99

Release v0.3.99

Fixed

  • Lightbox Preview Scrollbars: Eradicated an issue where scrollbars on the left accordion column and the far right of the builder window were causing the LightboxPreview to shift its layout when toggled on and off. Added aggressive scrollbar-width: none and ::-webkit-scrollbar { display: none !important; } rules across the preview container, accordion wrapper, and main split layout wrapper to guarantee rigid dimensions.
  • Lightbox Implementation Plan: Added an implementation_plan.md artifact to guide future work bringing Elementor Lightbox parity to VHBuilder (UI/Hover colors, Text colors, Fullscreen/Zoom/Share toggles, and Title/Description dropdowns), and prepared a toggle for "Force 16:9 Ratio".
5 Jun 2026
v0.3.98

Release v0.3.98

Added

  • Content Background & Settings Pickers: Added a comprehensive background editor to the Framework General panel for Content Background, Site Background, Lightbox Background, and Lightbox Close color. Each picker includes variable selection, manual hex input, and an inline dropper icon.
  • Variable Hover Previews: Integrated \onHoverVariable\ across color fields so that variable dropdown previews instantly display in the UI canvas without saving.
  • Auto-inversion for Dark Mode Variables: Instead of requiring users to select secondary specific dark colors manually, the CSS generator (\responsiveGenerator.js\) automatically emits the correct dark-mode inverse counterparts inside the \.dark\ class block (e.g., \--primary\ outputs \--primary-light-1\ in dark mode, \--base-10\ outputs \--base-90\).

Fixed

  • Fixed an issue where the \VariablePickerDropdown\ incorrectly prepended \--color-\ to root variables like \--primary\.
1 Jun 2026
v0.3.97

Release v0.3.97

Changed

  • Panel UI Refactoring: Replaced tab-based navigation with a smooth, animated accordion layout for both the Components Panel and Elements Panel.
  • Icon Update: Swapped out emojis in the Components Panel for clean Radix Icons, ensuring consistency with the rest of the builder interface.
  • Custom Elements Injection: The Elements Panel now dynamically creates a "Custom" category at the bottom, automatically populating it with your saved user elements so you can insert them effortlessly.
  • Simplified Actions: Removed the "Save Component" button from the Components panel to reduce clutter and streamline user actions.
  • Animation Glitches: Fixed layout shifts caused by scrollbars and missing margin pre-allocations, as well as fixing a CSS Grid 0fr animation bug by applying min-height: 0 to accordion bodies.
1 Jun 2026
v0.3.96

Release v0.3.96

Added

  • Interactive Edit Button Overlays for Canvas Chrome: Hovering over the header or footer preview inside the canvas now highlights the overlay with a dashed border and slides in a centered "Edit Header" or "Edit Footer" button. Clicking this button automatically redirects the builder context to edit the template.
  • Context-Specific Canvas Chrome Rendering: Header and footer overlays now only render when editing in page context (editingContext === 'page'). The settings options to toggle them are hidden from the Settings card when editing templates or layouts.
  • Template CSS inlining in Standalone Mode: The standalone builder's store initialization now prepends CSS style tags to headerHtml and footerHtml, preventing layouts from falling back to page-level column styling in standalone mode.

Fixed

  • Normalised API Template & Layout Load Format Compatibility: Fixed a bug where switchTemplate and switchLayout failed to recognize the direct template/layout objects returned by the WordPress and Standalone Node API adapters, which caused them to discard the returned data and load placeholder/dummy templates.
  • Removed Mask/Opacity Fading: Fading/opacity styling (opacity: 0.6) and click-blocking (pointer-events: none) have been removed from the header and footer chrome wrapper containers, making them display at full opacity and allow clicks on the Edit buttons while protecting normal page content selection.
29 May 2026
v0.3.95

Release v0.3.95

Added

  • Code prettification in the builder editors. HTML, CSS, and JS stored by WordPress (which serialises block content onto a single line) are now automatically formatted before being handed to the CodeMirror editors. Three new global helpers — vh_prettify_html(), vh_prettify_css(), and vh_prettify_js() — are defined in functions.php and called from every code-retrieval path (inline config, AJAX load-page handler, and REST API get_page_data). The HTML formatter uses a token-based regex splitter that tracks nesting depth and correctly handles void / self-closing elements. The CSS formatter splits by {} delimiters and re-indents declarations. The JS formatter detects minified (single-line) code and splits on {} and ; boundaries; already-formatted code with newlines is returned unchanged so custom indentation is never destroyed.
  • builder-template.php hides non-builder DOM injections. A CSS rule body.vh-builder-page > :not(#vh-builder-root):not(script):not(style):not(link) is injected via a <style> block so stray elements added by plugins or the active theme are hidden while the builder is open.

Fixed

  • **VH_HTML_To_Semantic_Blocks attribute extraction refactored into extract_attributes().** All element attributes (class, src, alt, href, target, rel, width, height, data-vh-loop*, and any other arbitrary attributes) are now extracted in one dedicated method and encoded into both the block attributes array and the rendered HTML attribute string. Handles <strong> and <em> as leaf elements, falling back all other unknown tags to container treatment.
  • **REST API block reconstruction handles Gutenberg-saved blocks without metadata.originalHtml.** VH_REST_API::reconstruct_html_from_blocks now includes a fallback path that rebuilds leaf and container element HTML directly from block attributes (cssClasses, imageUrl, imageAlt, linkHref, htmlAttrsList, loop attrs, etc.) when originalHtml is absent. This ensures pages created or edited via the WordPress block editor (which strips metadata) load correctly in the visual builder without a blank canvas.
  • **WordPress block editor no longer injects wp:vhbuilder/semantic-html markup into the builder's code editors.** The builder boot path (and REST/AJAX retrieval) now calls VH_REST_API::reconstruct_html_from_blocks() as the primary source of HTML, with VH_Semantic_Blocks_Parser::extract_html() and _vh_builder_html post-meta as ordered fallbacks. Raw <!-- wp:... --> comment wrappers are never surfaced to the editor views.

Changed

  • CSS and JS prettifiers strip excess blank lines. The CSS formatter collapses three-or-more consecutive newlines to two, and the JS prettifier always trims leading/trailing whitespace from its output.
22 May 2026
v0.3.90

Release v0.3.90

Fixed

  • Stopped escape-character corruption in nested semantic blocks. Pages saved through the builder were corrupting themselves over repeated saves — front-end rendered raw escape sequences (\\\\/figure>, \\\\"}} -->), image src URLs gained extra slashes (http:////////localhost:4000////...) and wrapping quotes, and post_content size ballooned until parse_blocks could no longer decode the JSON in any block. Root cause was VH_HTML_To_Semantic_Blocks::convert_container_element storing the entire inner block markup string inside the container's own metadata.originalHtml; each save re-encoded that string via wp_json_encode, doubling every \ and ", and reconstruction returned the fat originalHtml verbatim so the next save fed it back through the encoder. Container blocks now store only a skeleton <section class="X"></section> in originalHtml (no inner content, constant size), and VH_REST_API::extract_and_update_blocks rebuilds containers fresh from htmlTag + cssClasses + data-vh-loop* attrs + recursed innerBlocks. Leaf blocks (img, h\*, p, a, span) still use originalHtml since they have no children. Existing well-saved pages render identically; their next save writes clean skeleton markup and they become immune going forward.
  • **vh_filter_content no longer overrides correct block-rendered output with stale _vh_builder_html meta.** The filter now defers to do_blocks whenever post_content contains wp:vhbuilder/ markup, and treats _vh_builder_html as a legacy fallback for posts that pre-date the v0.3.88 block-as-source-of-truth migration.
  • **Builder boot path no longer empties the canvas when legacy meta is cleared.** vh_builder_scripts now reads the initial editor HTML via VH_REST_API::reconstruct_html_from_blocks against post_content, with VH_Semantic_Blocks_Parser::extract_html and _vh_builder_html as fallbacks. Previously, deleting the stale meta on save broke the next builder load because the boot path still expected the meta to carry the canonical HTML.

Changed

  • **vh_page_saved_in_builder actively clears legacy _vh_builder_html and _vh_builder_js post_meta on every save** so the legacy fallback in vh_filter_content can't resurface stale, escape-corrupted markup over freshly-saved block content.

Added

  • Avatar upload in the profile panel. New POST/DELETE /auth/avatar endpoints (multer in-memory storage, 5 MB cap, JPEG/PNG/GIF/WEBP only) resize uploads to 256×256 WebP via sharp and write to template-backend/uploads/avatars/{userId}.webp. The URL is persisted in users.avatar_url (migration 005_avatars.sql). Auth responses (/auth/me, /auth/login, /auth/mfa/verify, /auth/mfa/backup) now include avatar_url via the shared sanitiseUser() helper.
  • React side:AuthContext.PublicUser carries avatarUrl, axiosInstance.resolveAuthUrl() resolves relative /uploads paths against the auth API origin, SettingsAccountProfile gains a Profile Photo panel with upload/replace/remove buttons and client-side MIME + 5 MB checks, and BuilderNavigation's sidebar avatar renders the uploaded image (falls back to initials when not set).

UI

  • AiHelperPanel skips the ResizablePanel wrapper when it's the only panel in a side dock (fills available height) and locks to 500 px height only when sharing the dock with other panels.
  • StructurePanel context menu now renders via createPortal into document.body with position: fixed, so the menu can overflow the panel without being clipped. useStructureHandlers clamps in viewport coordinates (panelRect.left/right) rather than panel-relative.
  • Side-dock sizing fixes:ResizablePanel left/right wrappers get height: 100% and min-height: 0 so they collapse properly; StructurePanel relaxes min-width: 380px → min-width: 0 and sets overflow: hidden; CodeEditors picks up min-height: 150px so the editor pane doesn't collapse to zero; left rail in main.css switches from min/max-width clamping to plain width: 100%.
22 May 2026
v0.3.89

Release v0.3.89

Changed

  • TemplatesPanel simplified to a single full-width view. Removed the internal templates-internal-sidebar (Template Mode profile, All Templates / Global Search / Dynamic Tabs / Filter Facets / Custom Queries nav, "Publish to Market" mini-card, "Exit to Dashboard" button) so the templates grid now fills the entire workspace area. The panel exits via the existing X button in the header.
  • Removed the activeTab state and the four feature-placeholder views (search, tabs, facets, custom) that the sidebar previously toggled between. Those features will return as dedicated entry points rather than hidden nested tabs.

Fixed

  • Template cards now display a readable label. When the store-supplied template object has no template_type (which is the case for entries hydrated from localStorage / the WP vh_list_templates endpoint), cards previously rendered as a blank "DEFAULT" pill with no name. Added a getTemplateLabel() helper plus a TEMPLATE_LABELS map so the nine core templates (header, footer, index, single, archive, 404, 500, 502, 503) render as "Header", "Footer", "Index", "Single Post", "Archive", "404 Not Found", etc. Falls back to template.title then template.id for user-created templates.
  • Card React keys now fall back from template_type → id, eliminating duplicate-key collisions when multiple defaults arrived without a template_type.

Removed

  • templates-split-layout, templates-internal-sidebar, vh-sidebar-profile.templates-nav-profile, sidebar-nav, nav-item, nav-icon, nav-text, nav-label, nav-subtitle, sidebar-footer, marketplace-mini-card (local copy — the shared one in ComponentsLibraryPanel.css remains), and exit-templates-btn styles, plus all of their [data-theme="light"] counterparts in TemplatesPanel.css.

Added

  • .template-info (header layout) and .default-badge styles (dark + light mode) so the DEFAULT pill renders cleanly next to the new template name.
  • .templates-panel now uses flex-direction: row with overflow: hidden so the main area fills the workspace cleanly after sidebar removal.
22 May 2026
v0.3.88

Release v0.3.88

Added

  • vh_maybe_base64_decode() helper that auto-detects base64 payloads when the is_encoded flag is stripped in transit (WAF / mod_security). Heuristic requires the decoded text to contain at least one HTML/CSS/JS marker (<, !--, {, ;, (, :) so plain alphanumeric strings are never touched.
  • Builder-store tests in react-builder/src/store/builderStore.test.js.

Fixed

  • Save paths decode base64 correctly. Wired the helper into vh_save_content (page + layout), vh_page_saved_in_builder, vh_convert_html_to_blocks, vh_ajax_create_page, vh_ajax_create_template, and VH_Templates::save_template — all four paths now decode strictly when is_encoded=1 and fall back to auto-detection otherwise.
  • Self-heal on read. The the_posts filter and VH_Templates::get_template() now decode any base64 left in post_content / wp_vh_templates rows from saves that predate the decode fallback, so existing broken pages and templates render correctly without manual repair.
  • page.php renders blocks. Switched from do_shortcode(get_the_content()) to the_content() so do_blocks runs and the vhbuilder/semantic-htmlrender_callback executes instead of leaving <!-- wp:... --> comments verbatim in the rendered HTML.
  • VH_Templates::save_template() surfaces DB failures. Now checks the VH_Database::save_template() return value, logs $wpdb->last_error, and returns the error to the React client instead of silently reporting success.
18 May 2026
v0.3.87

Release v0.3.87

Added

  • Account dashboard inside the VHBuilder Dashboard (vh-settings-panel). Five new views matching the brand_assets/vhbuilder_account_security_dashboard.html design language:
    • SettingsAccountProfile — name, email + verified badge, plan, sign-out.
    • SettingsAccountSecurity — subscription summary, password reset, MFA enable/disable (wired to authApi.mfaStatus / mfaDisable / MFASetupModal), danger zone.
    • SettingsAccountBilling — plan summary with deep-links to vhbuilder.online/pricing and vhbuilder.online/billing.
    • SettingsAccountWpSites — connected WordPress sites table with status badges (Active / Stale / Lost), refresh, revoke.
    • SettingsAccountTrustedDevices — trusted-device list with single-device and bulk revoke.
  • SettingsAccountDashboard.css — shared panel / badge / toggle / button / table styles for the new views, with full light-mode support.
  • Account sidebar in BuilderNavigation — user header (initials avatar, name, email, plan badge) and three labelled sections (ACCOUNT, CONNECTIONS, BUILDER) modelled on the brand-asset mockup. Existing builder items are unchanged and grouped under BUILDER.
  • accountView store state + openAccountView / setAccountView actions in builderStore.js. Sidebar items call openAccountView('security') (etc.), which opens the settings panel and jumps straight to the right view; ESC inside a view steps back to the dashboard rather than closing.
  • useOptionalAuth hook (react-builder/src/auth/useOptionalAuth.ts). Returns the auth context or null, letting the same components run in standalone mode (with <AuthProvider>) and WordPress mode (without). Each account view shows a friendly "sign in" placeholder when no auth is present.
  • WP-sites API surface in React — listWpSites() and revokeWpSite(id) added to react-builder/src/auth/authApi.ts, with a typed WpSite interface mirroring the backend response shape.
  • Auto-open the VHBuilder Dashboard on login.LoginPage and MFAPage now drop a vh-open-dashboard-on-arrive flag in sessionStorage when navigating to /builder after a successful sign-in (or MFA verification or backup-code redeem). App.jsx consumes the flag exactly once after the builder finishes initialising and opens the settings panel. Manual reloads do not retrigger it.

Changed

  • BuilderNavigation sidebar visuals restyled to match image 2 of the brand-asset mockups: section labels, compact 12px nav items, orange left-border on active items, hover background, removal of the heavy per-item bottom borders. Light-mode rules added for every new class.
  • SettingsPanel header — title swaps to the active account-view name ("Security", "Billing", etc.) and a "←� Dashboard" back button replaces the horizontal tab nav while a view is active.

Notes

  • Profile editing endpoints are intentionally deferred (read-only inputs + hint in the panel body).
  • Account deletion button is disabled with a tooltip pending the destructive endpoint.
17 May 2026
v0.3.86

Release v0.3.86

Added

  • Auth stack in template-backend/: register, login, refresh, logout, me, password reset under controllers/auth/, mounted at /auth and /api/auth.
  • MFA (TOTP, email codes, backup codes, trusted devices) under controllers/auth/mfa/ and routes/mfa.js.
  • WP licence connection endpoints (wp-connect GET+POST, wp-validate, wp-disconnect, wp-sites list/delete) with AES-256-GCM token storage.
  • Auth utils (authDb, authHash, authTokens, authIssue, authEncryption, authTotp, authBackupCodes, authMailer, deviceName) and per-route rate limiters in middleware/rateLimiter.js. All /auth/* responses force Cache-Control: no-store, private with Vary on Authorization, Cookie, Origin.
  • MySQL migrations under template-backend/migrations/ (001_initial_auth, 002_mfa, 003_trusted_devices, 004_licences) with a custom statement splitter in migrateAuth.js. New tables use CHAR(36) UUIDs and DATETIME(3) UTC timestamps.
  • SQLite → MySQL data migration script (template-backend/scripts/migrateSqliteToMysql.js).
  • WordPress plugin licence stack (inc/licence/ + mirrored in build-output/vhbuilder-dist/inc/licence/): VHB_Licence AES-256-GCM token storage keyed off AUTH_KEY/SECURE_AUTH_KEY, admin UI, REST API client, and cron-based re-validation.
  • React auth UI with TypeScript (tsconfig.json, AppRouter.tsx, src/auth/*, src/pages/auth/*, src/components/auth/*): Login, Register, ForgotPassword, ResetPassword, VerifyEmail, MFA, Billing pages + AccountSecurity, MFASetupModal, TrustedDevices components.
  • VITE_AUTH_API_URL env var for api.vhbuilder.online.

Changed

  • CORS expanded to allow any *.vhbuilder.online subdomain via regex, plus explicit allowlist (localhost ports, vhbuilder.online, marketplace.vhbuilder.online).
  • Express server listens unconditionally so Phusion Passenger can boot it via require().
  • cookie-parser wired up with COOKIE_SECRET.
  • Bumped to v0.3.86.

Security

  • Added keys/ and *.pem to template-backend/.gitignore so generated PEM key material never reaches the index.
21 Apr 2026
v0.3.82

Release v0.3.82

Added

  • VHBuilder User-Created Element System (Phases 1, 2, initial 3) — 1896add.
  • Global Element Update System with site-wide version tracking, auto-updates, UI notifications, and a Ctrl+Shift+U shortcut; enhanced workspace layout logic — b1cc1be.

Fixed — Element Thumbnail Persistence & Marketplace Publishing

  • Resolved Element Thumbnails — Added preview_image column to element_masters table and updated backend API to store/retrieve Base64 preview strings.
  • Tightened Screenshot Cropping — Removed fixed-width constraints from the capture container in UserElementCreatorPanel.jsx to enable tight, zoomed-in thumbnails.
  • Marketplace Publishing Workflow:
    • Implemented Authorization Bypass for local development in middleware/auth.js.
    • Synchronized Category Whitelist between frontend and backend.
    • Fixed Payload Mapping in ExportDialog.jsx and useMarketplaceAPI.js (renamed license to license_type, added terms_accepted: true).
    • Added Type Column to marketplace_templates to enable correct filtering between Templates and Elements.
    • Fixed SQL Query Mismatch (17 values for 18 columns) in Template.js.

Between 0.3.82 and 0.3.86 (no version bump)

Three substantial commits landed between the 0.3.82 and 0.3.86 releases without their own version number:

  • 8813b88 — V2 Element System — comprehensive update to media handling and backend utilities.
  • 5d20af2 — V2 Element Editor refinements — media pipeline and light mode support.
  • 0917979 — Optimization and Cleanup — Structure Panel refactored for zero-reflow, boot sequence optimised with requestIdleCallback, canvas rendering enhanced, comprehensive console-log cleanup across core files.
18 Mar 2026
v0.3.81

Release v0.3.81

Refactored — Framework Panel Wizard UI

  • Extracted FrameworkPanel into 10 step components — new framework/ directory with FrameworkSpacingStep, FrameworkTypographyStep, FrameworkColorPaletteStep, FrameworkGapsStep, FrameworkRadiusStep, FrameworkSizesStep, FrameworkThemesStep, FrameworkCSSStep, FrameworkVariablesStep, FrameworkOutputStep.
  • Redesigned as timeline/wizard flow — sequential step navigation replaces the monolithic panel.
  • Refactored framework internals — frameworkConfig, frameworkGenerator, colorGenerator simplified and restructured.
  • Added FrameworkPanelUtils — extracted color utilities (hexToRgb, generateShades, generateTints, etc.).
  • FrameworkPanel.css — reorganized and reduced (~2700 lines refactored).

Changed

  • Default page scaffold — switched from data="header" attributes to semantic classes (.header, .container, .section); added CSS reset, flex layout, CSS custom properties for spacing.
  • Minor updates across page.php, ElementsPanel.jsx, PagesPanel.css, FrameworkPanelReducer.js, FrameworkPanelToolbar.jsx.
  • Layout/media UX fixes and auto slug syncing.
  • Unified layout creation and toolbar UI styling.

Added

  • Build tooling — build-launcher.bat, build-vhbuilder.js, build-vhbuilder.ps1 for streamlined builds.
  • BUILD_SETUP_GUIDE.md and QUICK_REFERENCE.txt — build documentation.

Removed

  • Deleted old zip archives — vhbuilder-manager-FIXED.zip, vhbuilder-manager.zip, vhbuilder.zip and all vhbuilder-manager-FIXED/ contents.
6 Mar 2026
v0.3.80

Release v0.3.80

Added

  • Page settings metadata flow, dark modal styling, and WP preview routing fixes.
  • Space support in BEM title editing with a helpful placeholder (required extensive debugging of a space-key-blocking issue in input fields).
  • Classes and IDs shown as separate deletable pills in the CSS editor header; pills are clickable with focus state and improved spacing.
  • Colorful SVG brand logo integrated into the toolbar.

Fixed

  • Internal path-based IDs (0-0-0) hidden from the ClassManager UI and the CSS/JS editor header selector display.
  • HTML/Structure panel synchronization restored in non-focus mode; HTML corruption while typing in the HTML editor fixed.
  • Element highlight calculation cleared correctly on deselection; spanning line-height measurement corrected in the Structure Panel.
  • TreeNode simplified by removing redundant child-measurement code.
  • Style panel: restored background-color swatch popup actions; auto-select first selector and target the selected CSS pill correctly.
27 Feb 2026
v0.3.58

Release v0.3.58

Fixed — Canvas Flicker on Keystroke

Root cause: Every keystroke in the HTML, CSS, or JS code editor called setHtml/setCss/setJs, which triggered the Canvas useEffect to set iframe.srcdoc — a full document reload that blanked the iframe on every character typed.

Solution: Direct DOM patching instead of iframe reload.

The Canvas useEffect now has two paths:

  • Patch path (all subsequent edits): Updates <style> textContent and body.innerHTML directly in the live iframe document. Zero blank flash. Instant on every keystroke. Handles HTML, CSS, JS, and frameworkCss changes.
  • Full reload path (first load only): Sets iframe.srcdoc as before to initialise the document.

Side effects fixed:

  • Event handlers are now re-attached with fresh closures on every patch, fixing a pre-existing stale isEditing capture in hover/click handlers.
  • Removed editingEl._cleanupEdit() from React effect cleanup — it was incorrectly stripping inline editing event listeners after the first keystroke of inline canvas editing.

Changed

  • Canvas.jsx — Added iframeInitializedRef, handlersRef, docRefForHandlers refs. Replaced single-path useEffect with patch/full-reload split. Extracted handleAutoSelect and extraStyles as shared locals. Removed prevJsRef (no longer needed). Simplified cleanup to onload = null only.

Testing

  • Typing in HTML/CSS/JS panels: canvas updates live, zero flicker ✅
  • Loading a new page: full reload fires correctly ✅
  • Inline canvas editing: guard unchanged, editing unaffected ✅
26 Feb 2026
v0.3.55

Release v0.3.55

> Note: two distinct pieces of work carry the 0.3.55 label in project > history — a documentation reorg + Gutenberg integration (dated 2026-02-26 > in git) and a component-creation fix session (recorded 2026-02-25). Both > are preserved here since the exact version boundary wasn't tracked > precisely at the time.

Added

  • Gutenberg block editor integration — validation fix, grid support, templates.
  • Documentation reorganized into a centralized .github/docs/ structure, with an organization standard added to AI instructions.

Fixed — Component Creation & Context Menu System

Component HTML Capture

  • Fixed component creation to capture only the selected element instead of the entire page.
  • Updated getComponentContent() to prioritize componentCreationTarget.selectedHtml from right-click context.
  • Priority order: right-clicked element HTML → store focused element → full canvas HTML → default.

Context Menu Edit Options

  • Fixed "Edit Component" option — now properly opens the component instance editor.
  • Fixed "Edit Component Definition" option — now properly opens the component definition editor.
  • Added component metadata extraction in tree building (data-vh-component-id, data-vh-component-name).

Component Instance Editor Panel

  • Fixed empty panel issue by passing the correct data structure ({ componentId, html }) instead of just an HTML string.
  • Panel now populates with component properties and allows editing instance values.

Changed

  • useStructureTree.js — Now extracts component metadata from HTML during tree building.
  • ComponentCreatePanel.jsx — Improved HTML content selection priority logic.
  • useStructureHandlers.js — Refactored handleEditComponent and handleEditMainComponent.
  • StructurePanel.jsx — Added customComponents for full component definition lookup.
25 Feb 2026
v0.3.52

Release v0.3.52

Changed — CSS Architecture Restructure

  • Migrated from an aggressive, monolithic CSS approach to a surgical, class-based architecture.
    • Removed all: revert !important blanket resets from block editor styling.
    • Created VH_Style_Loader class for organized CSS management (separates frontend vs editor contexts).
    • Moved from inline CSS injection via block_editor_settings_all to proper WordPress hook-based loading (enqueue_block_assets).
    • CSS now loads via standard wp_enqueue_style() instead of raw innerHTML injection.
  • Minimal Block Editor CSS — replaced 144 lines of `all: revert !important` overrides with 30 lines of surgical, WordPress-specific fixes.
  • WordPress Native Layout System — grid layouts now use WordPress native layout attributes instead of raw CSS Grid; detect_grid_layout() added to the HTML-to-blocks converter, auto-detecting BEM classes like programs-list/grid-3 and injecting `layout: { type: 'grid', columnCount: 3 }`.

Added

  • inc/class-vh-style-loader.php — new class-based CSS management system (enqueue_frontend_styles(), enqueue_editor_styles(), with cache-busting via filemtime).
  • Semantic block labels via metadata.name.
  • One-click homepage export with block conversion.
  • Dynamic CSS enqueuing for builder pages.

Fixed

  • Backend storage enforced as the source of truth (no localStorage) for the web-based builder; page switching, page persistence, and page-content flicker on load all fixed.
  • Pages panel filtered to show only WordPress pages (not posts), across all post statuses including drafts; status badge CSS/values corrected.
  • Canvas hover flickering and repeated image reloads eliminated.
  • vh_load_page now reads/writes the same post-meta keys as vh_save_content; page context preserved across refresh when switching between pages.

Removed

  • Aggressive all: revert !important rules and the vh_add_styles_to_block_editor() / block_editor_settings_all filter.
18 Feb 2026 – 21 Feb 2026
v0.3.4 – 0.3.36

Release v0.3.4 – 0.3.36

Rapid same-week iteration; version numbers were bumped per notable commit and weren't always sequential (e.g. 0.3.17 jumps to 0.3.27, several in-between numbers were never used).

  • 0.3.4 (02-18) — Elements panel with keyboard shortcuts and documentation; version-number housekeeping.
  • 0.3.5 (02-18) — Dashboard left sidebar implementation complete.
  • 0.3.6 (02-18) — Sidebar auto-show and settings panel persistence.
  • 0.3.7 (02-18) — Elements Panel redesign with tab navigation and rich HTML templates.
  • 0.3.8 (02-18) — Elements Panel integration complete: auto-selection, parent insertion support, modifier keys, visual polish.
  • 0.3.9 (02-18) — Enhanced Style Panel: Settings tab with element properties.
  • 0.3.10 (02-18) — Settings Tab UI/UX redesign and panel positioning fix.
  • 0.3.11 (02-19) — Grid Generator Modal: two-tier Settings layout (simple vs. complex properties), context-aware property visibility by display value, nth-child selector fix, CSS Grid label-left layout.
  • 0.3.12 (02-19) — Grid Generator complete: resize support, saved state, unique grid-item classes instead of nth-child selectors, fixed grid-area boundary and cleanup bugs.
  • 0.3.13 (02-21) — ClassManager & Code Editor UI enhancements, plus a large React Doctor code-quality pass across ~25 commits: useState → useReducer refactors (ComponentsPanel, EditComponentMainPanel, StockImagesTab, ComponentCreatePanel, CustomComponents, App.jsx), accessibility fixes across modals and CodeEditors, memoized style constants, code-splitting for heavy components, Zustand selector optimisation, score raised from 86 to 90+.
  • 0.3.14 (02-21) — Button-style class pills and CSS header improvements; 38 form-label accessibility fixes (htmlFor attributes).
  • 0.3.15 (02-21) — AddElementModal: unified class/ID input system; CSS header alignment fix.
  • 0.3.16 (02-21) — Canvas AddElementModal: direct modal on right-click, replacing the context menu.
  • 0.3.17 (02-21) — Removed AddElementModal overlay background.
  • 0.3.27 (02-21) — Complete URL parameter fix (vh=builder implementation); modal overlay centering/transparency, Vite base path for WordPress asset loading, panel position persistence merge order.
  • 0.3.28 (02-21) — Console errors fixed and non-critical notification cleanup.
  • 0.3.29 (02-21) — Framework storage refactor: custom database table and reset functionality.
  • 0.3.30 (02-21) — Fixed framework backend storage persistence.
  • 0.3.31 (02-21) — Fixed WordPress admin framework display; framework persistence permissions and debug logging.
  • 0.3.32 (02-21) — Framework detection fix (check CSS first); version numbers synced in style.css and SettingsPanel.
  • 0.3.35 (02-21) — Media Panel animation system complete: Pages and Media panels dock left like Settings; slide-out animation added to all overlay panels.
  • 0.3.36 (02-21) — Page loading and AJAX compatibility fixes, plus a second major React Doctor optimization campaign across ~35 commits: further useState → useReducer consolidation (FrameworkPanel, StructurePanel, GridGenerator, SettingsPanel, Canvas), large-component extraction (StockImagesTab, SettingsModal, ElementSettings, BuilderNavigation, ComponentCreatePanel), accessibility roles added throughout, warnings reduced from 115 to 5 (99/100 final score).
2 Feb 2026 – 17 Feb 2026
v0.1.4 → 0.3.6

Foundational Build

The initial ~144-commit build-out before per-commit version tracking began (established 2026-02-17 per the project's first status report, baseline v0.3.3). Major areas of work, grouped by theme:

VH Framework

  • Added the VH Framework foundation — a CSS framework positioned to compete with ACSS — with a full Framework Panel UI, database persistence, and a generated-features view.
  • Converted the Framework Panel to a full-screen overlay sliding in from the left; iterated extensively on positioning, collapse behaviour, and generated-feature display.
  • Added WordPress backend framework API endpoints with graceful handling of a missing backend.

BEM Classes & CSS Focus Mode

  • Added "Create BEM Classes" to the Structure Panel context menu, made it recursive for children, and auto-generated CSS rules on creation.
  • Added focus mode for CSS and JS panels (matching the HTML panel), with exact class matching to prevent parent/child BEM class bleed-through and proper merge logic for focused updates.

Component System

  • Added the Edit Main Component Panel and Edit Component Definition panel, with visual property-linking mode and automatic prop-placeholder insertion.
  • Converted EditComponentPanel from a modal to a left-sliding side panel; replaced raw HTML editing with an editable prop form.
  • Fixed component creation/editing/insertion across many edge cases: format normalization between old/new component shapes, props and HTML/CSS/JS support in the custom-components API, cross-DOM insertion compatibility, and default property value application.

Media & Stock Images

  • Added a Bricks Builder parser with gradient and icon support.
  • Built out a full stock-images system in phases: search/filter UI, favorites, collections (with DB tables and API), image preview modal, search history, keyboard-shortcut reference panel, collection detail view, right-click insert, and image-replacement mode.
  • Implemented Media File Optimization (MVP), then auto-optimization on upload with WebP/AVIF format support and safer file-replacement cleanup.

Structure Panel, Style Panel & Canvas

  • Added the StylePanel accordion with two-way CSS sync and var() autocomplete; directional grid layout with link modes and CSS shorthand support.
  • Added draggable canvas resize handles (Radix UI DragHandleDots2Icon); replaced SVG icons with Radix UI icons throughout.
  • Fixed ResizablePanel drag/resize behaviour, StructurePanel drag delay and tree wrapping, and StylePanel slide-out re-animation issues.

Store & Code Quality

  • Refactored builderStore.js from 1,714 lines down to 179 by extracting logic into focused modules.
  • Standardized button styles across panels and fixed Zustand hook-ordering bugs in StylePanel.
VhBuilder Logo 1.jpeg
Builder

The WordPress page builder that works your way — pure code, pure visual, or anything in between.

Product

FeaturesPricingRoadmapJoin Alpha

Resources

DocumentationMarketplaceChangelog

Company

VivaHostingPrivacy PolicyTerms of UseContact
© 2026 VhBuilder — a product of VivaHostingPrivacy · Terms · Contact