xSpeed Cache is officially live! Get 50% OFF during Launch Week — Lifetime starts at just $79Lifetime from $79 — 50% OFF, Launch Week! See Plans →

See Plans →
xSpeed Hub Pricing Docs Blog Scan
Appearance
Get Plugin

What's new in xSpeed Cache

Every release, every fix, every improvement, tracked in one place.

xSpeed Cache Free

v1.4.2

2026-10-12

Combine CSS now works on Flywheel and Bedrock installs, Elementor Pro sticky headers stick under Delay JS, and a failed pass on the finished page can no longer cache an empty page.

Caching

New Every wp-admin page says when the page cache is off, and names the cache it would replace when another one already serves pages.
Improved Purge All also clears Nginx Helper's Redis page cache, as used on GridPane, EasyEngine and WordOps.
Improved `wp xspeed cache purge <url>` purges only that page, and the purge says which server cache it reached.
Fixed When a filter on the finished page returns nothing, the rendered page is kept. An empty page is no longer sent or cached.
Fixed Adding, moving or editing a widget clears the cached pages.
Fixed With LiteSpeed Cache installed, the conflict check follows its page-cache setting, including its 24-hour pause.
Fixed An Nginx Helper that is installed but not set up is no longer taken for a server cache.
Fixed Purging no longer leaves an expiry marker beside pages that carry a nonce, which flooded response headers with errors when Query Monitor was active.

Optimization

New The Asset Manager has a card on the Optimization page.
Fixed Combine CSS works when wp-content is outside the WordPress folder, as on Flywheel and Bedrock.
Fixed Under Delay JS, jQuery ready callbacks wait for the replay, so Elementor Pro sticky headers attach and Elementor entrance animations show.
Fixed Async CSS holds transitions until the stylesheets apply, keeps them when JavaScript is off, and skips entrance animations already on screen.
Fixed Turbo Render works with the page cache off, and skips sections that break under containment.

Object Cache

Fixed Redis connects over a unix socket, reading the same constants as Redis Object Cache.

Dashboard & Admin UX

Improved The expert-setup offer links to the booking page on xspeedcache.com.
Fixed Database Clean deletes posts and comments through WordPress, so trashed media files go too, and a clean that runs out of time says how much is left.
Fixed Deleting a post detaches its child posts of another type.
Fixed The scan report is stored as JSON, so a latin1 database table no longer loses it.
Fixed The PageSpeed tab shows only with a licensed Pro, appears as soon as the licence is activated, and stays out of settings search while hidden.
Fixed The xSpeed Cache menu is hidden from users who can't manage options.

v1.4.1

2026-10-08

Cloudflare Enterprise setup now runs in four short steps, and the add-on's offer opens its page in the dashboard, shows with any version of Pro, and goes away once the add-on is bought.

Cloudflare

New The Cloudflare Enterprise add-on can show its setup as four steps (Setup, Verify, Connect, Done), with a card for each DNS record and a Copy button beside every value.
Improved "Get it" on the sidebar's Cloudflare Enterprise card opens the add-on's page in the dashboard, in the same tab, instead of the store. That page explains what you need and has the buy button.
Improved The sidebar card and the add-on's page show the price the service reports.
Improved The Cloudflare Enterprise card on the Network page has a glowing border until the add-on is on. With reduced motion turned on, the border stays but does not move.
Improved The add-on's page links to its setup guide.
Improved The header shows the add-on's state as soon as its licence or domain changes, without a reload.
Fixed The sidebar shows one Cloudflare Enterprise card, with any version of Pro.
Fixed With a Pro older than 1.3.0, the Network page keeps the Cloudflare Enterprise card and page, and a licensed Pro is asked to update.
Fixed The offer is hidden once the add-on key is entered, and on sites whose host already provides Cloudflare Enterprise.

v1.4.0

2026-10-07

Saving a post now clears only the pages it changes instead of the whole cache, sites on xCloud's Cloudflare Enterprise get every purge passed to the edge, and pages whose address uses non-Latin characters are cached and purged correctly.

Caching

New Saving a post, a comment or a product clears only the pages that change: the post itself, its archives, and the listing pages that show it. The whole cache is cleared only when the change reaches a list the theme draws on every page, such as a menu or a Recent Posts widget, and the purge log says why.
New `wp xspeed cache listings` shows the pages that run a post list of their own.
New Add-ons can send CDN headers on cached pages.
Fixed Pages whose address uses non-Latin characters, such as Chinese or Arabic slugs, each get their own cache entry. They could share one, and a slug with no Latin letters could overwrite the home page's cached copy.
Fixed A purge clears such a page however the browser spells its address, and Excluded URLs pasted from the address bar now match.
Fixed Opening wp-admin no longer empties the page cache and the edge.
Fixed Updating a WooCommerce product purges once, and a stock change purges its pages in one batch.
Fixed Making a post sticky, including outside the editor, clears the blog page.
Fixed Publishing in the Customizer purges the cache.
Fixed Content and site purges no longer delete minified CSS and JS files.

Cloudflare

New On sites where xCloud provides Cloudflare Enterprise, every purge goes to xCloud's purge plugin, from WP-CLI and cron too, and Purge All sends one whole-domain purge.
New xCloud's purge plugin counts as proof that the site is behind Cloudflare.
Fixed The edge no longer keeps a page longer than the page's own lifetime, so forms on cached pages stop failing once their nonce expires.
Fixed Pages served for an address with tracking parameters, such as `?utm_source=`, are no longer stored at the edge, where a purge could not reach them.
Fixed The edge may store a new page only once xSpeed has written it, and not while the page is still being optimized.
Fixed Edge headers are kept on cached pages Apache serves through an internal redirect.

Health

New Health warns when Cloudflare stores pages that were marked do-not-store.
New The nginx rules panel says whether the server runs the current rules block, and remembers that you pasted it.

Optimization

Fixed Minified and combined files are named by their content and by site, so a changed source file is never served from an old copy.
Fixed Delay JS restarts its 15-second replay deadline each time a delayed script arrives, so slow pages finish replaying.
Fixed Smart Delay never parks the inline snippets of a script that is already running, and consent-banner protection ignores the site's own domain.
Fixed Text set in the Font Library or theme.json shows at once while its fonts load.
Improved Turbo Render holds a deferred section's images and videos until the section is near.

Media

New Autoplay videos can start after the page has loaded. Off by default.
Fixed Autoplay videos stay out of the click-to-play facade, and the video restorer respects Excluded Images.
Fixed Images in footer popups load a smaller file on phones.

Resource Hints

Fixed Device-scoped LCP preloads fetch only the hero image for the visitor's device.

Preloader

New With Separate Mobile Cache on, the preloader warms the phone copy of each page too.

Object Cache

Fixed Switching from another object-cache plugin works without a conflict, and switching back restores that plugin on a clean namespace.

AI / MCP

New A site can be connected from xSpeed Hub through a consent page in wp-admin.
New get_site_info reports add-on licences.
Fixed The site token is never sent to a redirect target, and a connection code works only once.
Fixed Saving settings over MCP could remove the site's Hub connection.
Fixed Destructive commands need confirmation however they are called.

Dashboard & Admin UX

New The Cloudflare Enterprise add-on has its own entry under Network, a sidebar card and a purchase screen.
Fixed A Pro module shows the Pro lock while Pro is unlicensed.
Fixed Dashboard requests work on sites whose REST address carries a query string.
Fixed The dashboard no longer shows a second scrollbar.

v1.3.7

2026-10-01

Pages with a background-video hero now paint the hero text first, Load CSS Asynchronously no longer makes pages flash unstyled, sites in a multisite network stop sharing cached REST responses, and a site whose token changed can reconnect to xSpeed Hub.

Media

Fixed A hero's background video (autoplay, muted, looping, no controls or poster) now starts on the visitor's first scroll, tap, key press or mouse move, so the hero text paints first instead of waiting for the video's first frame.
Fixed Only one image per page gets high fetch priority, instead of every image counted by Eager-load First N Images.

Optimization

Fixed Load CSS Asynchronously leaves stylesheets render-blocking unless the page has critical CSS, so pages no longer paint unstyled and then shift. Google Fonts, Bunny and Typekit stylesheets still load without blocking.
Fixed A page builder's row, column and section stylesheets stay render-blocking, so a builder hero no longer snaps into its grid after the first paint.
Fixed Under Delay JS, a script's inline data now waits with the script, so the script never runs without its data.
Fixed Combine CSS recognises another plugin's non-blocking stylesheet however its onload handler is written, instead of merging it into a print-only file.
Fixed Strip jQuery Migrate works when another plugin, such as Elementor Pro, loads the script registry before Bloat Control.

Resource Hints

Fixed When a background video opens the page, images below it are no longer preloaded as the LCP image.

Caching

Improved More click and campaign IDs are ignored in the cache key, on saved lists too.
Fixed Each site in a multisite network gets its own cached REST responses. Two sites requesting the same route could be served each other's data.
Fixed Installing a new plugin no longer empties the page cache as if live code had been replaced.
Fixed A request that measures a page's CSS is never answered from cache, whatever Ignored Query Parameters say.
Fixed xSpeed's own warming, benchmark and verifier requests, and bot hits, no longer count in the hit ratio or in site analytics.

AI / MCP

New Extensions can add hidden MCP tools, and oversized MCP request bodies are refused.
Improved The generate_critical_css tool builds Critical CSS for any page, not only the home page.
Improved get_cache_status reports the Site Icon.
Fixed A site whose MCP token changed can reconnect to xSpeed Hub. The Hub gets the new token, and a new credential clears its lockout.
Fixed The attach route no longer returns the admin's user ID.

Dashboard & Admin UX

Improved Settings labels and hints are rewritten in plain language and sentence case.
Fixed Leaving onboarding from the last step lands on the dashboard instead of a broken #[object Object] page.

v1.3.6

2026-09-28

Smart Delay postpones the scripts other delay modes had to leave running, LCP background images and video posters are preloaded, LiteSpeed servers get the same static fast path nginx and Apache already had, lightbox videos open with their player instead of a blank window, and Turbo Render no longer clips designs that overlap their neighbours. Emojis can be switched off, post revisions capped, and inline background images held back until they scroll into view.

Media

New Background images set in an element's inline style can be lazy-loaded. Each one loads just before its element scrolls into view, the first ones on the page load straight away (the Eager-load First N Images count), and with JavaScript off every background loads as before. Off by default.
Fixed A video embed inside a lightbox's hidden template (Essential Addons, Magnific Popup, Lity) is no longer swapped for the click-to-play facade — the popup opened blank because lightbox styling only sizes an iframe. The template's iframe stays lazy, so it still loads nothing until the popup opens, and the list of template classes can be extended with the xspeed_video_facade_popup_classes filter.

Optimization

New Bloat Control has a Disable Emojis toggle. It removes the WordPress emoji script and styles from pages, feeds, emails, embeds and wp-admin. Off by default.
New Turbo Render has an Excluded classes setting. A deferred section clips content that hangs over its boundary — a card overlapping the section below it, for example — so a section listed here always renders right away.
Fixed Turbo Render leaves any section holding an iframe alone. Deferring a map or video holder gained nothing and could paint it over content that overlaps it by design.
New Smart Delay. Delaying every script used to quietly skip any script that inline code depends on — on builder pages that was most of them. Smart Delay postpones those scripts anyway and parks their inline snippets with them, replaying everything in page order on the first interaction. Off by default; the exclusion list and consent-banner protection still win.
Improved Delayed scripts now replay the way a real page loads — in page order, with the document's readyState moving through its normal stages, and with each script's DOMContentLoaded and load handlers firing when its turn comes.
Improved A delayed inline loader now waits for the scripts it injects, a throwing inline module no longer stalls the replay behind it, and the replay works on pages with a hash-based Content-Security-Policy.
Fixed The replay no longer touches scripts and handlers the page ran normally — their writes, listeners and onreadystatechange calls behave exactly as before Delay JS was switched on.
Fixed A consent banner is only delayed by an entry that names it; a second protected token on the same tag now needs naming too.
Fixed A script whose author opted out of optimization late in the page no longer loses the defer attribute a stamper had already given it.

Resource Hints

New LCP background images declared in <style> rules and video poster images are now detected and preloaded, so hero sections painted from CSS backgrounds get the same head start as <img> heroes.

Caching

New LiteSpeed servers can opt into the static-rewrite fast path, serving cached pages before PHP starts — the same shortcut nginx and Apache sites already had.
Fixed Publishing a post on an nginx host no longer purges the server's entire cache — only the pages the post touches. Nginx Helper's own off switch is respected, and a content import ends with one server purge instead of one per post.
Fixed The admin-bar purge button answers immediately and runs the purge in the background, instead of holding the request open until some hosts cut it off.

Database

New Limit Post Revisions keeps only as many revisions per post as you choose, and 0 turns revisions off. A WP_POST_REVISIONS value in wp-config.php still wins, and the panel shows it.

Migration

Fixed Importing LiteSpeed Cache settings no longer turns oEmbed off when the site had emoji removal on. That setting now maps to Disable Emojis.
New WP Rocket's emoji, embeds and CSS background lazy-load settings are imported.

Dashboard & Admin UX

Fixed The Cloudflare upsell no longer advertises an edge cache TTL the APO module does not set.

v1.3.5

2026-09-22

Consent banners now survive Delay JS on every site that ships one, Turbo Render works on any theme rather than only Elementor, JS-injected YouTube/Vimeo embeds load only on click, and nginx sites are no longer told to fix a configuration that was already correct.

Media

New YouTube and Vimeo players that a theme or plugin injects with JavaScript after page load now get the same click-to-load facade as regular embeds, so no player code loads until a visitor presses play.

Optimization

New Turbo Render works on any theme or page builder. It recognises Divi, Bricks, Oxygen and Beaver Builder sections directly, and where no builder is recognised it falls back to the page's own structure, so the feature is no longer inert outside Elementor.
Improved Turbo Render is the new name for the feature previously called Render Skip — the same mechanism, named for what the visitor gets rather than what the browser postpones.
Fixed Consent banners from Cookie Notice, Moove, Termly, Usercentrics, Iubenda, OneTrust, Borlabs, Real Cookie Banner and SureCookie are never delayed, so a visitor is always offered the choice before leaving.
Fixed Complianz and NotificationX banners stay protected even when another plugin strips the id WordPress prints on their script.
Fixed An author's data-no-optimize, nowprocket or similar opt-out is now read as an attribute rather than matched anywhere in the tag, so a script is neither wrongly delayed nor wrongly skipped because the marker appeared in a URL, a class or a neighbouring inline block.
Fixed A script you name yourself in the Delay JS target list is now delayed even when it is a consent banner — the built-in banner protection yields to an explicit choice.

Health

Fixed nginx sites with a working configuration are no longer told to paste in a server snippet they already have. Site Health and the dashboard now reach the same verdict, and a check that cannot conclude says so instead of warning.

Preloader

Fixed Cache warming no longer identifies itself in a way that common firewall rule sets block, so newly published posts are warmed again on sites running 7G/8G-style protection.

v1.3.4

2026-09-20

Consent-manager scripts marked late are now always left alone, below-fold sections skip rendering work until they are needed, and xSpeed's MCP server shares a site cleanly with other MCP plugins.

Optimization

New Below-fold sections are rendered lazily with content-visibility: auto, so the browser skips their layout and paint work until they scroll into view.
New Block-editor stylesheets are stripped from anonymous frontend pages that do not use any blocks.
Fixed Scripts that another plugin marks data-no-optimize or data-no-minify late — as consent managers such as Borlabs Cookie do — are restored to their original URL and left alone by minify, defer and delay, however late the marker is stamped.

AI / MCP

Improved The AI & agents screen now leads with the MCP server and says what each of its tools does, with descriptions shown in full.
Improved An assistant already connected over OAuth may ask for approval once more after updating — nothing needs re-entering, and read-only connections stay read-only.
Fixed An AI assistant can now connect to xSpeed and to another MCP plugin on the same site. xSpeed's OAuth details moved to an address of their own under /xspeed/mcp, and the site-wide address is handed over as soon as another plugin asks for it — where nothing else wants it, xSpeed keeps answering there.

Dashboard & Admin UX

Fixed Buttons can carry a border and always show keyboard focus, and the Cloudflare Dev-mode controls use proper button styling.

v1.3.3

2026-09-16

Consent gets a dashboard home, the cache engine learns to leave non-HTML alone, and uncacheable pages now tell the CDN so.

Privacy & Analytics

New A "Privacy & usage data" panel to view and withdraw usage-analytics consent any time, with a matching wp xspeed privacy command.
Improved The setup wizard's analytics consent now defaults to off and is only ever an explicit opt-in.

Caching

Fixed WordPress's virtual robots.txt (and favicon) is no longer cached or minified, so every directive and newline reaches crawlers intact.
Improved /robots.txt joined the default cache exclusions, and the sitemap pattern now matches sitemaps.xml too — existing installs keep their working exclusion through the rename.

Cloudflare & CDN

New A page xSpeed refuses to cache now sends no-store edge headers, so a CDN never freezes a half-optimized or excluded page.
Fixed The deferred Cloudflare purge batch is bounded, cleared on deactivation, and says so when a purge is refused.

Optimization

Fixed Scripts marked data-no-optimize or data-no-minify are left completely alone by minify, defer and delay — consent-manager configurations always ship current.
Fixed xSpeed's own scripts are never deferred or delayed by its own optimizer.
Fixed The Conservative preset now switches LCP preload and preconnect off, matching its "page cache + GZIP only" promise.

Dashboard & Admin UX

Improved Preload now reports what actually happened — how many pages are warming, and the server's reason when a crawl cannot start.

Reliability

Improved Uninstall now removes all usage-tracking state, the scheduled send, and every leftover option row.

v1.3.2

2026-09-15

Purging is now a contract other caches can join: clearing xSpeed's page cache also invalidates LiteSpeed Cache and the host's nginx FastCGI cache, and every purge is scoped to exactly the site and pages it was asked for — including on multisite.

Caching

New A purge-event contract lets other caching layers invalidate together with xSpeed, so a purge clears every cache that matters in one action.
New Purge All is forwarded to LiteSpeed Cache and the host's nginx FastCGI cache when they are present.
Fixed One post change triggers exactly one invalidation, deleting a media file purges again, and a purge still finds its post when the hook hands over none.
Fixed Purges are scoped per site on multisite — a purge no longer sends another site's URLs to this site's server cache, a default port is not treated as a different site, and full purges stay on the current site.
Fixed A purge listener that throws no longer aborts the purge, a query string of "0" is still treated as a query, and a partial purge reports itself as partial instead of claiming success.

Optimization

Fixed Delaying JavaScript no longer breaks inline scripts bound to a delayed handle, and replayed external scripts keep their original load order.

v1.3.1

2026-09-14

Purge all now says what it actually cleared, on the button and in the toast, instead of claiming success when a store refused. Pro features are marked with one lock everywhere rather than amber squares and crowns, which also lifts the dimmed labels back to readable contrast. The Cloudflare panel is staged by connection state, so setup comes before the actions that depend on it — and the auto-purge switch is visible while disconnected instead of hidden.

Dashboard & Admin UX

New Purge all reports its outcome — Cleared, Already empty, Partly cleared or Purge failed — and the toast names the files and size cleared plus any other store, or the reason a store refused.
Fixed Pro features are marked with a single lock in the teal tint. Locked tabs are no longer dimmed to 70%, which had dropped their labels below readable contrast, and the amber squares, crowns and sparkles are gone from the tabs, badges and the sidebar tier slot.
Fixed Turning caching on no longer flashes "Another plugin owns the page cache on this site" while the toggle is in flight. A genuine foreign drop-in still shows the banner.
Fixed The Purge all button keeps its natural width at rest instead of reserving room for the outcome label.

Cloudflare

New The panel is staged by connection state — Connection, then Actions — so credentials and Verify come before the buttons that need them, and an action that cannot work is disabled with a hint rather than failing silently.
Fixed The auto-purge-on-purge switch is always visible, dimmed while disconnected, instead of being hidden until connected. Hiding it is how the edge-sync switch went unnoticed.

Documentation

Fixed The full changelog moved to changelog.txt, shipped with the plugin and linked from the plugin page. wordpress.org truncates a changelog over 5,000 words on import, so the history past the cut had been dropped.

v1.3.0

2026-09-13

A single page can now be purged straight from the admin bar, the post list or the editor, and known third-party scripts — analytics, chat widgets, tracking pixels — are delayed automatically without asking you to list them. A host or agency can pin any setting from wp-config.php with a constant: the dashboard shows the pin, names the constant, and lets an admin take the setting back. xSpeed can also take over an abandoned page-cache drop-in, with your consent, instead of being blocked by it forever.

Caching

New Purge a single page from the admin bar, the post list's row actions, or the editor — and the purge confirms what it actually removed instead of assuming.
New `wp xspeed purge` clears every cache in one call, and a purge is scoped to exactly what the caller asked for.
New Publishing or updating a post also purges the pages that list it, not just the post itself.
New An abandoned page-cache drop-in left by another plugin can be taken over with one consenting click, and a leftover husk of a drop-in no longer blocks caching forever.
Fixed A migration handover now completes instead of stopping halfway, from the dashboard and the CLI alike.
Fixed xSpeed no longer mistakes itself for a competing cache plugin.

Optimization

New Known third-party scripts are delayed until interaction automatically, including the inline install snippets vendors ask you to paste into the header.
New Font stylesheets are deferred out of the render path, and a Google Fonts request that blocks rendering is rewritten to swap.
New A manual preload list covers the images no detector can see.
Fixed The LCP preload no longer picks a brand logo over the page's real hero image.
Fixed Deferring no longer breaks inline scripts that depend on another handle, combining no longer swallows scripts that delaying protects, and handle exclusions are honoured in the delay pass.
Fixed Valid minified JavaScript is no longer rejected, asset URLs are matched across schemes, an uploads folder at the domain root is recognised, and `?ver` is kept on files plugins rewrite in place.
Fixed Lazy loading reads an image's size from whichever attribute holds its URL, and no longer mistakes a real image for a placeholder because of a word inside its filename.

Settings

New Any module setting can be pinned from wp-config.php with a constant. The dashboard shows a pinned field as read-only and names the constant that holds it.
New An admin can take a pinned setting back — the override displaces the host's constant and only that.
Fixed A panel containing a pinned field saves again, and editing a pinned setting is a single inline edit.

Object Cache

New Redis credentials and Memcached servers are read from wp-config.php, and `WP_REDIS_PREFIX` is honoured as a key salt.
Fixed Cache keys are always namespaced per site, so two sites sharing a Redis or Memcached database can no longer read or purge each other's entries.
Fixed The dashboard panel gained every fix that had only reached the CLI, owns only what the plugin itself wrote, and no longer presents another plugin's object cache as xSpeed's.

Reliability

Fixed Translations now load for both PHP and the dashboard, and the settings screens are translatable.
Fixed nginx sends one Cache-Control header per location instead of two, and the de-duplicated header no longer caches 404 responses.
Fixed An audit contributor that throws no longer takes the whole audit down with it, and add-ons can report findings of their own.

AI tools

Improved The optimize assistant honours its cooldown, never measures without consent, keeps the score through a run of failures, and reports the newest score with its age.

v1.2.4

2026-09-06

The Overview now reports what is actually switched on, counted from the server rather than guessed from the payload, and a new xSpeed Scan grades the site from inside the plugin. Pages carrying a security token can use the fast static path again instead of silently falling back, and nginx users can now fetch their server config from the command line.

Dashboard & Admin UX

New The master cache switch now sits in the top bar, reachable from every screen.
New The sidebar collapses to a rail, and adapts on smaller screens.
New An (i) beside a module's pill explains why it is reported as on, where the rule is not obvious.
Fixed The Overview counts the features that are genuinely on. It previously counted entries in the payload, including ones that never rendered, so the number disagreed with the screen.
Fixed On/off state refreshes after a save, so counts update without reloading the page.
Fixed Collapsing the rail no longer shifts the content beside it, and rows keep their size.
Fixed The collapsed rail shows real tooltips rather than the browser's own, and the drawer is now reachable by keyboard.

Caching

Fixed A page carrying a security token can use the fast static path again, expiring on the token's clock instead of being refused outright.
Fixed A refusal that silently disabled static serving is now surfaced rather than left to guess at.
Improved The cache signature records when it was generated.

Speed Test & Scan

New An xSpeed Scan runs from inside the plugin and grades the site, with a score ring on the Overview.
Improved The Speed Test page reports both Lighthouse scores, organised into tabs.
Fixed A scan claims its slot atomically, so two runs cannot collide, and the card recovers when a poll fails.

Optimization

Fixed A CSS background hero is now preloaded as an LCP candidate.
New `wp xspeed cache nginx-config` prints the server-block config, so an installer or provisioning script can fetch it without the dashboard. It assumes nginx on a site no request has reached yet, and `--server=` states the answer outright.

v1.2.3

2026-09-02

xSpeed now recognises which plugin owns the page cache and refuses to take it, so installing beside WP Rocket, WP Super Cache or LiteSpeed no longer switches thirteen features on behind you or leaves two page caches competing. Switching caching on is now all-or-nothing, so a half-finished attempt can no longer leave a site with a broken wp-config.php. Combining CSS no longer strips a site's styles when Critical CSS is on, and page builders can be edited again.

Caching

New xSpeed recognises which plugin owns the page cache before switching anything on, and stands down when the field is taken. A site already running another cache plugin installs with every feature held off and that plugin's files untouched, instead of coming up with thirteen switches on.
New Switching page caching on is now all-or-nothing. The drop-in, the wp-config.php line, the rewrite rules and the settings are written as one step and rolled back together if any part fails, so a half-finished attempt can no longer leave the site in a state it cannot recover from.
Fixed Enabling the cache no longer corrupts wp-config.php, and a refusal is no longer reported as success.
Fixed The dashboard now names the plugin that blocked page caching instead of silently switching the toggle back off, on the dashboard and at the end of the setup wizard.
Improved The dashboard reports whether the cache is actually serving pages, rather than what the setting says it should be doing.
Improved Conflicting plugins are identified from one catalogue rather than two lists that had drifted apart. Swift Performance was missed entirely, and Autoptimize was wrongly reported as a page-cache conflict.
Fixed A "left cache files behind" note now names only the plugin that could have left them, and xSpeed no longer blames itself for its own cache folder while inactive.
Fixed A stray WP_CACHE line left in wp-config.php by a removed plugin is no longer mistaken for another plugin owning the cache. A site with no cache plugin at all installed with everything switched off while the wizard said no conflicts were found, and reinstalling could not fix it, because uninstalling left those switches behind.
Fixed Hosts that were never in conflict are no longer refused.

Optimization

Fixed Combining CSS no longer leaves the site unstyled when Critical CSS is on. Sheets deferred by Critical CSS were mistaken for print-only stylesheets, merged into a print-only bundle and stripped of the swap that applies them, so visitors were served a page with no styles at all.
Fixed A Google Fonts stylesheet is no longer cut in half when CSS is combined. Font addresses carry semicolons inside them, and the rule was truncated at the first one.
Fixed Delaying JavaScript no longer rewrites attributes belonging to other plugins, and a script keeps its own type.
Fixed Minification stands down on page-builder editing screens. Beaver Builder, Elementor, Divi, Brizy and Oxygen edit over a front-end address rather than inside the dashboard, so their editors were being minified and broken.
Improved The combined stylesheet is minified as one file, rather than only the parts that went into it.

Integrations

New Another WPDeveloper plugin can now install xSpeed for you and have it come up with page caching on and nothing else switched on, without either plugin carrying its own copy of the rules.

AI tools

Improved Tools generated from the plugin's own commands now describe themselves for an assistant rather than for a terminal, so an AI agent picks the right one more often. This covers most of the tools on a Pro site.

v1.2.2

2026-08-31

Forms on cached pages stop being rejected, because a page is no longer served for longer than the security token it carries. Stores keep their cache through orders and reviews while price and stock changes actually clear it, the cache lifetime you configure is finally the one enforced, and the AI tools can no longer delete content without showing you what they found first.

Caching

Fixed A form on a cached page no longer fails to submit. A cached page could outlive the security token baked into it, so on any site set above 24 hours every anonymous form: contact, checkout, add-to-cart, course enrolment, was rejected with the other plugin's own error message. Pages carrying a token now expire with it, and pages without one keep the full lifetime.
Fixed The cache lifetime you configure is now the one that is enforced. The fast path applied a fixed 24 hours regardless of the setting, so a 12-hour lifetime served pages for up to 25 hours, and a 7-day one rebuilt the page from scratch for 6 days out of 7. Per-post expiry overrides now reach it too.
Fixed Editing a template, template part, global styles, a navigation menu or a synced pattern clears the cache again. None of those has a page of its own, so a Site Editor change updated nothing visitors could see until the lifetime ran out.
Fixed Saving a cache setting no longer replaces another cache plugin's drop-in on a site where xSpeed page caching is switched off. That could leave the site with no page cache at all after xSpeed was later switched off.
Improved The activity log now names what triggered each purge, "Cache purged (hook:wp_update_nav_menu)" instead of a bare number.
Fixed A damaged compressed copy of a cached page is no longer sent to visitors. A copy that was cut off part-way through cannot be decompressed, so the browser threw away the page it had and drew a blank one instead. Compressed copies are now written in one step so a half-written one never becomes visible, and each is stored with its own length so one that does not match is skipped and the normal page is served.

WooCommerce

Fixed A price, sale or stock change now clears the product's cached pages. Those are written straight to the database without the hook the cache listened for, so a store could quote one price on a cached page and charge another at checkout for the whole cache lifetime. The product page, the shop archive, its category and tag archives and a storefront front page are all cleared.
Fixed Placing an order, a customer registering at checkout, or a visitor leaving a product review no longer wipes the entire site's cache. Guest reviews are on by default, so any visitor could flush a store's cache repeatedly with no account. A review now clears only the page it was left on, and only once approved.

AI tools

Fixed The database cleanup tool can no longer permanently delete posts, revisions and comments without a scan first. A scan now issues a single-use token bound to what it found, and the cleanup refuses without one: including through the general command route, which previously bypassed the check entirely. Both tools now state plainly that the deletion cannot be undone.
New A public signals route (/xspeed/v1/signals) reports the plugin version and whether the AI server and Hub are connected, so external audit tools can identify the site. No tokens, accounts or paths are exposed.
Fixed An admin who is deleted or removed from a site no longer leaves the site reporting a Hub connection that no longer exists.

Migration

New The import offer now migrates in place. Pressing Import in the notice previously only navigated to another screen and asked you to find the button again; the consequence, that migrating deactivates the old plugin, is now stated under the button rather than in a dialog after the click.
Fixed A migration that worked no longer leaves both cache plugins active. The handover was refused whenever any part of the import fell short, and enabling the object cache always fails on a host without Redis or Memcached: so two page caches were left running, which is the exact conflict deactivating exists to prevent. An optional module that could not be enabled is now a footnote, not a failure.

Recommendations

Fixed Pro features that are already switched on are no longer recommended for purchase. Image conversion is enabled per format and runs on defaults with nothing stored, so a site converting every upload was still told to buy image conversion, forever.
Fixed Recommendations reappear when Pro is deactivated or its licence expires. Pro leaves its settings behind, so reading those rows alone silently hid the suggestions on a site that was no longer running the feature.

Health

Fixed Browser caching is reported from the headers actually served, not from xSpeed's own snippet. A site whose caching headers come from its host, a container or a proxy was permanently warned about a problem it did not have and could not act on. A probe that fails to complete no longer counts as proof of a missing header.

v1.2.1

2026-08-27

Self-hosted videos no longer download in full before anyone presses play, the autopilot now undoes a change that makes the site slower instead of calling it verified, and the diagnosis finally reports the content problems it was measuring all along.

Optimization

Fixed A self-hosted video with its own preload setting is no longer skipped. "Lazy-load HTML5 videos" now overrides a player's preload="auto" or "metadata", which is where the setting was meant to help, a page carrying a 924KB video no longer transfers it before anyone presses play. Autoplaying videos are left alone.
New The click-to-play facade now covers self-hosted videos that have a poster image, not just YouTube and Vimeo embeds. The file downloads on click; without JavaScript the original video is still there.
New Each optimization step is now measured, and a change that makes the page measurably slower is undone instead of being reported as verified. A change inside normal run-to-run variation is reported as unchanged rather than claimed as a win.
Fixed An image the theme has already marked as the most important one on the page is no longer lazy-loaded, which delayed the very image it was told to prioritise.

Diagnosis and reporting

Fixed The reported score came from the oldest audit on record rather than the newest, so re-measuring never moved the number. The newest successful run is now used, and a failed audit is never presented as the current score.
Fixed Page weight, heavy videos and DOM size were measured but never shown. The content problems only a person can fix are now reported alongside the settings the plugin can change itself.
New The last audit's own named opportunities, with their measured savings, now feed the diagnosis, routed to either the settings the plugin can change or the content a person has to.

Reliability

Fixed A missing plugin file no longer takes down wp-admin. xSpeed now stops cleanly and names the file that is missing, so the Plugins screen still loads and the plugin can be switched off to recover.
Fixed An unresolvable class is reported with the path of the file that is missing, rather than only the class name, so an interrupted update or a quarantined file can be identified from the log.

Caching

New The cache is cleared when a plugin, theme or WordPress core is updated, so a page is never served from markup the updated code no longer produces. It clears network-wide on multisite, can be switched off, and leaves the cache alone for a plugin you installed but never activated or for a nightly language-pack update.
Improved Visitors arriving with a tracking parameter such as utm_source, fbclid or gclid are now served from the fast path instead of loading WordPress in full.
Fixed Add-ons can now read the signal that says the cache was already cleared by an update, so the cache is no longer cleared a second time.

Settings and AI tools

New A setting that is accepted but has no effect on your server now says so. Enabling Brotli on a server without Brotli support reported plain success while nothing changed; the tools that flip the setting now report the same warning the dashboard shows.
Fixed A URL field that is posted to now rejects an address that cannot be called. An email address entered in one of these fields was silently accepted and the feature then failed with nothing on screen to explain why.
Fixed Score history now reports whether each audit succeeded, and the error when one did not, so a failed run is no longer indistinguishable from a run that returned no score.

Dashboard

Fixed Switching tabs on Health & insights no longer jumps the page back to the top.
Fixed A shorter tab is no longer padded out to the height of the tallest one, which left a screen of blank space below the content. Tab strips are also fully wired for screen readers and keyboard navigation.

Setup wizard

Fixed The wizard opens with Balanced selected instead of no preset, warns in both directions when a setting is changed away from the preset, and uses the same labels throughout.
Fixed A brand-new install showed all three preset cards as inactive, because nothing had been configured yet. The cache lifetime also starts at 7 days rather than empty.

v1.2.0

2026-08-24

One command now measures your site, applies the settings that help, and undoes anything that breaks. Four cache-poisoning routes are closed, importing from W3 Total Cache carries settings across faithfully instead of a handful, and combined JavaScript keeps running in the order the page expects.

Security

Fixed A page rendered with a query string is no longer stored under the bare URL's cache key, where it would then be served to every visitor asking for the plain URL.
Fixed Percent-encoded query keys can no longer poison the cache. Two spellings of the same key resolved to different cache keys, so a crafted URL could seed the entry a normal request would later read.
Fixed An allow-listed tracking parameter no longer lets a crafted URL overwrite a cached page.
Fixed A search-results page no longer poisons the homepage through the cache key.

Optimization

New wp xspeed optimize and the optimize_site AI tool make the whole tuning loop one command. It measures the site, applies the recommended settings one at a time, re-checks the page after each change, and reverts anything that breaks it, then reports what it applied, what it undid and why, and what it could not reach at all (page weight, hotlinked images, DOM size) rather than claiming a win it did not make.
New Images hosted on another domain get their real dimensions resolved, so lazy loading and the preloader no longer skip them.

Migration

Fixed Importing from W3 Total Cache brought across 8 of 510 settings. Page cache, browser cache, object cache, exclusions and compression now map to their xSpeed equivalents.
Fixed Disabling W3 Total Cache's master Minify switch is now respected. Its child CSS/JS settings stay populated while the master is off, so reading them alone imported minification and combination as enabled on a site that had deliberately turned them off.
Fixed An encrypted Redis password that cannot be read is now reported rather than silently dropped, so the object cache no longer fails to connect with nothing on screen to explain why.
Fixed An object-cache endpoint written as tls://host:port imported a host that could never resolve. The host and port are now imported and the dropped transport is stated, since xSpeed connects over plain TCP.
Fixed Compression enabled only for "other" file types no longer imports GZIP as switched off.
Fixed A partial import no longer switches off the plugin it imported from, and no longer shows a finished "Imported" state with no way to retry.
Fixed WP Super Cache is detected and imported. Its settings are stored under different keys than the importer looked for, so it reported nothing to import.
Fixed Page caching is actually enabled by an import that says it is.

Cache

Fixed Ignored query parameters are matched by whole name rather than as substrings, so utm_source no longer matches an unrelated parameter that merely contains it.
Fixed Purging a URL on a non-standard port deleted nothing.
Fixed Query-string requests skip only the cache write, not the HTML transforms, so those pages keep their minification and lazy loading.

CSS & JavaScript

Fixed Combined JavaScript is split by print group, so scripts registered for the footer are no longer hoisted into the head and run before first paint.
Fixed The combined bundle is carried on an existing handle rather than a new one, preserving inline payloads attached to it and the surrounding cascade order.
Fixed Configuration a page builder attaches late. Elementor writes elementorFrontendConfig on wp_footer, long after combining runs. Now prints ahead of the combined bundle instead of behind it, so scripts no longer initialise against a config that does not exist yet.

CDN

Fixed Changing the CDN URL clears Elementor's render caches, which stored the previous URLs in their markup.

Interface

New The MCP server appears on the Overview as a capability card, so an AI connection can be set up without hunting for the panel.
Fixed The setup wizard and the ⌘K search palette no longer render underneath the WordPress admin menu.
Fixed Opening a panel no longer shifts the page behind it when the dashboard is scrolled away from the top.
Fixed The Apply button on a Pro recommendation works instead of failing silently. Free and Pro name their recommendations differently, and only Free's were understood by the button both of them use.

MCP server

Fixed OAuth discovery keeps working when another plugin claims /.well-known/.

Server configuration

Fixed URL exclusions are mirrored into the generated nginx snippet, so nginx no longer serves cached copies of pages xSpeed was told to exclude.

v1.1.8

2026-08-20

Importing settings from another caching plugin no longer switches that plugin off without asking. Purging CSS or JavaScript now also clears the pages that link them, a failed save no longer reports success, and another MCP plugin's AI connections keep working alongside xSpeed.

Migration

Fixed Importing settings no longer deactivates the plugin you imported from as an unavoidable side effect. The panel now offers both outcomes, "Import & switch to xSpeed" and "Import settings only". Previously the only way to decline was Cancel, which also abandoned the import; WP-CLI and MCP did the opposite and left both plugins running silently. All three now behave the same way.
Fixed On a multisite network, a single site's administrator can no longer switch off a network-activated caching plugin for every site on the network. WordPress refuses the same action from its own Plugins screen.
Fixed Choosing to leave the other plugin running now raises a Health item naming the plugin and the risk, so two page caches competing for the drop-in don't go unnoticed. It clears itself once the plugin is switched off.
Fixed LiteSpeed's exclusion lists are stored as JSON and were imported literally, so imported exclusions never matched anything.

Cache

Fixed Purging CSS or JavaScript now also purges the pages that link those files. Cached pages could keep pointing at deleted combined assets, leaving them unstyled until another page purge happened to occur.
Fixed A single POST request no longer keeps a visitor on the uncached path for the rest of their visit. One form submission or comment previously meant every later page was generated from scratch.
Fixed The cache now purges when any module's settings change, not only the cache module's.

CSS & JavaScript

Fixed "Defer" and "Delay" now apply to the external script itself rather than to an inline block queued before it, so execution order is preserved.
Fixed Combined JavaScript keeps its declared dependencies, so scripts no longer run before the libraries they need.
Improved Inline style and script blocks are now minified, and anything deliberately skipped says why.

Settings & interface

Fixed A failed save no longer shows the green "Settings saved" toast, and the failure stays visible instead of disappearing with it.
Fixed Settings writes carrying keys that would be silently dropped are now refused rather than accepted and discarded.
Fixed A cleared URL field stays cleared instead of reverting to its previous value.
Fixed Sub-sections of a disabled feature now collapse with it.
Fixed A failing server snippet now identifies the problem instead of showing only a status code.

MCP server

Fixed xSpeed no longer answers another MCP plugin's OAuth discovery URLs. Its rule could match every .well-known discovery address on the site and return xSpeed's details, which stopped AI assistants connecting to other MCP plugins correctly.

Security

Fixed The MCP server's dynamic client registration is now bounded, limits on stored clients, redirect URIs, name and URI length, plus per-IP rate limiting on the registration endpoint.
Fixed MCP and WP-CLI settings writes are now gated on the Pro licence, matching the dashboard.

v1.1.7

2026-08-17

On a multisite network, a change to one site no longer wipes every other site's cache. Cache cleanup no longer deletes stylesheets a live page is still using, and a consent banner styled by another plugin stays styled.

Cache

Fixed On a multisite network, each site's cache is now cleared on its own. Changing a setting, publishing a post, or clicking Purge on one site previously deleted the cached pages of every other site on the network, so the cache was rarely warm for anyone.
Fixed Cache cleanup no longer deletes a combined stylesheet or script that cached pages are still pointing at. Those pages carried on being served while their CSS and JavaScript returned "not found", leaving a site unstyled and unresponsive, and invisible to the owner, whose own browser still held the old copy.

CSS & JavaScript

Fixed "Load CSS Asynchronously" no longer breaks a stylesheet another plugin has already made non-render-blocking. A cookie-consent banner in that position loaded with none of its styling applied, both logged in and logged out.

Settings

New List settings: cache exclusions, ignored parameters and the rest. Now show the stock value beside the box you edit, with a Reset action to restore it. These are lists where one wrong entry can quietly stop a whole section of the site being cached, and there was previously no way to see how far a list had drifted.
Improved The box you edit is now labelled, and Reset sits on it rather than beside the defaults.

Accessibility

Fixed Hint text, captions and status pills now meet the AA contrast minimum in light mode. The worst affected was the "Off" state pill, the only thing communicating whether a feature was on.

v1.1.6

2026-08-13

A search-results page could be cached and served as your home page. Combining CSS no longer strips a site's styling, Pro settings can no longer be changed without an active licence, and an AI assistant now reports this site's tier and audits the page you actually asked for.

Security

Fixed A single search request could replace your cached home page. With search caching on, one visit to a search URL was stored as the site's front page, so every later visitor, and search engines, were served those results instead. The cached copy was handed out by the web server without WordPress running, so it kept being served until the cache was cleared. Search pages are now kept out of that store entirely.

CSS & JavaScript

Fixed Combining CSS files could leave a site completely unstyled: no missing files, no errors, just the theme's styling gone. WordPress can inline a stylesheet it considers small, and doing so dropped the combined file that every other stylesheet had been folded into. Combining now happens on the finished page, after WordPress has made those decisions, so what you see in the browser is what was combined.
Fixed A stylesheet saved with a byte-order mark, common in files edited on Windows, no longer breaks the styling of every file combined after it.
Fixed Fonts and stylesheets brought in by an @import rule are no longer dropped when their file is combined with others.

AI assistants & WP-CLI

Fixed On a site without an active Pro licence, Pro settings can no longer be changed through WP-CLI or an AI assistant. The dashboard already showed them locked; four write routes and the image recommendation did not enforce it, so a change made that way appeared to succeed.
Fixed A refused change is now reported as a refusal. It previously returned success over settings it had not written, in both the REST response and the command's exit code.
New run_score runs an external performance audit from any install, and honours the provider you configured, asking for GTmetrix no longer silently runs PageSpeed Insights instead.
Fixed An AI assistant asking what this site is now gets the truth about its tier. On a Pro site with a lapsed licence it previously reported the licence as active.
Improved A PageSpeed audit started from an assistant now measures the page you asked for. It previously measured the home page whatever URL was given, and reported success.

Cache

Fixed Turning the page cache off, or uninstalling xSpeed, now removes the WP_CACHE setting it added to your wp-config.php. It was only removed when written exactly one way, so most sites kept a stale setting behind after the cache was switched off, including after the plugin was deleted.

Compatibility

Fixed wp xspeed purge no longer clears the page cache on Apache servers without mod_headers, where the cache could not be served from disk anyway.

Accessibility

Fixed Two buttons, the nginx snippet's copy control and the MCP panel's tool list. Now show a focus ring again when reached by keyboard. They suppressed the outline entirely, which left anyone navigating by Tab with no indication of where they were.

Settings

Improved Duration fields now show what the number means in plain words, "6 hours", "1 day 12 hours", for every value, not only round ones.

v1.1.5

2026-08-11

AI assistants can change your settings again, and the cache preloader works on sites without a readable sitemap.

AI & agents

Fixed An AI assistant can read and change your xSpeed settings again. The two tools that do this were dropped from the catalog on every site, so an assistant, including the one connected through the Hub, was told they did not exist and could only fall back to raw commands.
New wp xspeed settings list / get / update. Read and change any module's settings from the command line, and from an AI assistant through the same commands.
Improved Settings for Pro features are no longer readable or writable over WP-CLI or an AI connection on a site without an active licence. The dashboard already hid them; these two surfaces did not.
Improved Credentials still cannot be set from the command line or an AI assistant. Asking to now names the field it refused rather than reporting success over an unchanged key.

Preloading

Fixed On a site whose sitemap can't be read, the preloader now warms your most recent pages straight from your content instead of silently queueing nothing. This affected two common setups that are not misconfigurations: sites discouraging search engines (where WordPress disables the sitemap outright, standard on staging and pre-launch sites), and SEO plugins that serve their own sitemap at a path we were never told about.
Fixed When a crawl can't start at all, the preloader panel now says "Couldn't start" and names the reason, rather than reporting "Ready" over an empty run.
Improved The explanation appears while the crawl is running, not only once it finishes, on a large site that is the difference between watching an unexplained crawl for hours and knowing why on the first tick.
Fixed wp xspeed preloader status no longer fails with an internal error after a crawl that ended with nothing queued. An AI assistant asking why a preload failed now gets the actual reason instead of a type error.

Branding

Improved New xSpeed Cache logo and wordpress.org banners.

v1.1.4

2026-08-10

Stored credentials are now encrypted, exclusions are enforced by the server itself, and the cache cleans up after itself.

Security

Fixed Stored credentials. API tokens, keys, and object-cache passwords: are now encrypted at rest and never returned in full by the dashboard, REST API, or an AI assistant. They were previously readable in plain text by anyone who could reach those endpoints. Existing values are encrypted automatically on upgrade; nothing needs re-entering.
Improved An AI assistant can no longer write credentials unless you explicitly grant it that permission when connecting.
Improved Cloudflare settings are verified when you save them, so a wrong token or zone is reported straight away instead of failing silently on the next purge.

Caching

New Expired cache entries and orphaned minified assets are now collected on a schedule, so the cache directory no longer grows without bound on a busy site.
Fixed Excluded cookies and bypassed user agents are now enforced on the fast path the web server serves directly. Previously they applied only while a page was cold, so a warm page could serve the shared anonymous copy to carts, members and bypassed bots.
Fixed Sites using TranslatePress now cache the translated page rather than the untranslated one.
Improved Response headers now distinguish a cache miss from a deliberate bypass, so a quick header check shows whether a page is about to be cached or was skipped on purpose. Previously both came back with no header at all.
Improved With debug mode on, a bypassed response also names which rule skipped it, logged-in, excluded URL, query parameter, and so on.
Fixed Cache hits are now counted on every server, not only nginx, so Apache and LiteSpeed sites no longer show a permanent 0% hit ratio.
Improved The static-rewrite check now reports a known blocker (such as Separate Mobile Cache) instead of a bare "inactive", and says the same thing in the dashboard, WP-CLI, REST and MCP.
Improved The hit ratio now excludes 404s and bot traffic, and reports the origin only when a CDN sits in front, so the number reflects what your visitors actually experience.

Compression

Fixed GZIP is no longer reported as inactive when the check itself couldn't complete. A blocked loopback request is not evidence that compression is missing, and telling you your server was misconfigured because we couldn't reach it was the bug. Only a check that positively proves GZIP is absent now warns.

Optimization

Fixed The CDN now serves CSS, JavaScript and fonts, not just images from post content. Font files also get the CORS header they need when loaded cross-origin.
Fixed LCP preload now picks the largest image on the page instead of the first one, so the preload helps the image that actually decides your LCP score rather than competing with it.
Fixed Brotli is detected on nginx by asking the server, so a host with ngx_brotli installed is no longer told to install it. A check that can't complete now says so rather than reporting Brotli as unavailable.
Fixed The Compression page no longer promises an nginx snippet that isn't on it. It links to the snippet instead, and the link is there whether or not compression is already working.

Dashboard & Admin UX

Fixed Enter now inserts a newline in the "one per line" settings fields (Excluded URLs, Excluded Cookies, and the rest). Typing a list previously merged every line into one.
Fixed The Setup Wizard starts from your site's real settings, so re-running it and pressing Apply no longer silently switches off options you had turned on. A cache expiry that isn't one of the presets is shown as its own option and named before anything overwrites it.
Fixed The Recent activity feed shows setting names as they appear on screen instead of internal storage keys, and no longer writes connection details or account identifiers into the log.
Fixed Links to Tools → Migration now open that page rather than dropping you on the Overview.
New Settings fields can now link to their documentation; the PageSpeed API key field points at the setup guide.
Fixed External Score now lives in one place, under Health & insights. It previously rendered a second copy of the same settings and run history inside the Health page's PageSpeed tab.

AI & agents

Fixed A read-only MCP connection can now read status through every per-command tool. It previously refused the whole tool if any of its actions could write, so an assistant with read-only access could not inspect state at all. Write actions are still refused, and an unrecognised action is refused rather than allowed.

v1.1.3

2026-08-05

A redesigned dashboard, a homepage cache-poisoning fix, and caching that survives a plugin update.

Security

Fixed A crafted URL could poison the homepage cache, causing search-results content to be served to every visitor from the cached homepage.

Caching

Fixed Updating the plugin no longer silently disables page caching until the next admin login. The drop-in is restored on activation.
Fixed Cache hits served statically by Apache are now reported and counted, instead of showing a permanent 0% hit ratio.
Improved Health now explains when the fast static-cache path is unavailable because the server lacks mod_headers, and what to change, instead of suggesting a fix that cannot work.
Improved Fresh installs now start on the recommended profile, so sites set up by WP-CLI or a skipped wizard get compression, browser caching, and minification by default.

Dashboard & Admin UX

New Redesigned dashboard, new typography, colour system, navigation rail, and top bar, with grouped navigation and a consistent module-settings layout.
New Command palette for jumping to any setting.
New A dedicated Pro page describing what each Pro feature does.
New "Avg saved" card on the Overview, showing the real per-request time saved from your latest benchmark.
Improved License, Branding, and Multisite are now cards of their own, so the license form is one click away instead of three.
Improved Fonts now lives in one place under Optimization, and the page that used to host it is now "Media Optimization".
Fixed Recommendation links on the Overview now open the screen they point at, and "Get the snippet" opens the snippet.
Fixed The brand mark no longer renders black against the dark rail in light mode.

Optimization

New Delay JavaScript now also covers scripts printed directly into the page, analytics, pixels, and chat widgets that previously bypassed it entirely.
New The delay-JavaScript failsafe timer is now configurable, so it can be tuned or switched off instead of firing mid-measurement.
Fixed Delayed scripts are now matched correctly when minification rewrites their URLs.
Fixed HTML minification now says when it is deliberately suppressed by debug mode, instead of reading as on while changing nothing.

AI / MCP

New Stored PageSpeed Insights and GTmetrix history is now readable from your AI assistant.
Fixed Removed fifteen duplicate tools that shadowed the typed ones, trimming the tool list.
Fixed An unrecognised migration command now reports an error instead of silently succeeding.

v1.1.2

2026-07-30

A new Overview dashboard, click-to-play video embeds, and a full audit trail for AI actions.

Dashboard & Admin UX

New Overview screen is now the landing page, showing cache status, key stats, recommendations, and recent activity at a glance.
New PageSpeed and GTmetrix scores on the dashboard.
New Stat cards open into drill-downs so you can see what is behind each number.
Improved Notice buttons now take you straight to the control they refer to.
Improved Deactivating the plugin now asks for feedback, so problems reach us instead of going unreported.

Optimization

New Click-to-play facade for YouTube and Vimeo embeds, the player loads only when a visitor presses play, cutting page weight.
Fixed Minified HTML no longer loses the space between inline elements, which could run words together.

AI / MCP

New Audit trail recording every AI tool call, with an activity panel showing what was run and whether it changed anything.
New Every xSpeed CLI command is now available as its own MCP tool.
Fixed AI tool calls failed with a server error instead of running. Every tool works again.

Onboarding

Improved Account connection moved to the final step, so caching is set up before you are asked to sign in.
Fixed Returning from account setup now resumes on the right step.
Fixed Each "next step" card in the wizard now goes to its own destination.

Health

Fixed No longer tells you to configure your server when the check could not reach a verdict.

v1.1.1

2026-07-27

Actionable dashboard insights, richer AI tooling, and smarter health detection.

Dashboard & Admin UX

New Impact hero showing the real-world speed gain your cache is delivering, with a one-click next-best-action to apply the top recommendation.
New Benchmark history and daily hit-ratio trend charts, annotated with the setting changes that moved them.

AI / MCP

New Purge a single URL, read site health, test the object cache connection, and verify Cloudflare credentials directly from your AI assistant.

Health

New Detects third-party cookies that would poison the page cache and names the plugin responsible.
New Warns when the cache lifetime is shorter than the preloader interval, which would leave pages permanently uncached.

Optimization

New Delay individual scripts by name instead of all-or-nothing, so you can defer heavy third-party embeds while leaving critical scripts alone.
Fixed Lazy-loaded images now get correct width and height even when the theme strips WordPress' image size class, preventing layout shift.

Caching

Improved Benchmark now reports the real compressed transfer size alongside the uncompressed page weight.

Object Cache

Fixed A failed write to Redis or Memcached no longer leaves a stale value served from the backend.

v1.1.0

2026-07-22

New xSpeed Hub. Connect one AI assistant to manage caching across all your sites.

xSpeed Hub

New "xSpeed Hub" tab in the MCP Server panel. Connect this site to your xspeedcache.com account so a single AI connection can manage caching across all your WordPress sites.
New One-click "Connect via xspeedcache.com". Sign in and approve, no token to copy.
Improved The connect flow carries your admin email so account setup is one click for new users.

Dashboard & Admin UX

Improved Benchmark and AI audit now sit above the cache settings for a clearer, action-first layout.
Improved The dashboard menu now reads "xSpeed Cache".

v1.0.9

2026-07-15

Redesigned dashboard navigation, improved settings experience, and caching reliability fixes.

Dashboard & Admin UX

New Redesigned settings navigation with dedicated pages for Optimization, Cache, Compression, Cloudflare, Health, and AI & Agents.
New Branded loading skeleton for a smoother dashboard loading experience.
Improved Clearer and searchable settings navigation.
Improved Enhanced search with tab and section-level results.
Improved Cleaner Free dashboard with streamlined Pro sections.

Optimization

Fixed Improved CSS combination compatibility with page builders.
Fixed Resolved frontend rendering issues on block themes.

Caching

Fixed Admin bar cache purge issue.
Fixed Hit counter reset reliability.

v1.0.8

2026-07-13

MCP support for AI assistants, LCP optimization, and admin experience improvements.

AI / MCP

New MCP server support for Claude and other MCP-compatible AI assistants.
New Secure OAuth 2.1 connection for remote AI assistants.
New Read-only and read/write access controls with dashboard management.
New MCP dashboard with available tools and permissions.

Performance

New Resource Hints with LCP image preload and font preconnect.
Fixed Improved LCP image loading by preventing lazy loading on the hero image.

Dashboard & Admin UX

New Settings shortcut from the WordPress Plugins page.
Improved Updated admin menu organization and dashboard navigation.
Improved Better Pro license messaging and settings search experience.
Fixed Checkbox rendering in both light and dark mode.

Reliability

Fixed Improved cache permission handling on non-NGINX servers.

v1.0.7

2026-07-02

Improved reliability, granular cache management, Redis compatibility, and asset optimization fixes.

Caching

New Granular cache purge options for Page/Static, CSS/JS, Object Cache, and REST Cache.
Fixed Improved compatibility with previously installed caching plugins.
Fixed Purge All now properly clears optimized assets, object cache, and triggers CDN/edge purges.

Object Cache

Fixed Redis 6+ ACL compatibility for managed hosting environments.
Improved Object cache write verification for better reliability.
Improved Site-specific object cache flushing for shared Redis environments.
Improved Persistent object cache group flushing.

Asset Optimization

Fixed Combined CSS now preserves inline styles and stylesheet order.
Fixed Combined CSS files are regenerated correctly after cache purge.
Fixed Relative asset paths are preserved in optimized CSS.

Dashboard & Admin UX

Fixed Dashboard layout issue with large WordPress admin menus.
Fixed Admin menu and toolbar overlay issues.
Fixed Pro sidebar item ordering.

Migration

Fixed Mobile cache migration compatibility for NGINX static cache.

v1.0.6

2026-06-25

New caching surfaces, conditional settings, Pro warming features, and a large round of QA fixes.

Caching

New REST response cache layer with per-route TTL, repeated REST reads are served from cache instead of re-running the handler.
New Feed, 404, and search-results caching seams, feeds replay their content-type, cacheable 404s share one per-host entry, and search pages cache per normalized term (opt-in).
New xspeed_should_cache write-side filter so add-ons can opt requests in or out of the cache.
New Maintenance-aware serving, the cache stands down (via a drop-in sentinel) while the site is in maintenance, so visitors never get a stale "we'll be right back" page cached.
Improved Query-form feeds (/?feed=rss2) and conditional GET now return 304 Not Modified for unchanged responses, saving bandwidth for aggregators.
Fixed The PHP serve path and drop-in now honor the per-entry .meta (status, content-type, TTL) on every fast path, so cached 404s/feeds serve correctly.
Fixed The cache drop-in is version-stamped, so serve-logic changes reach existing sites on update instead of running stale.
Fixed Cache is purged when a user or term changes, not just on post edits.

Settings

New Conditional fields. Settings can declare dependsOn (with AND/OR groups) so dependent options only show/enable when their parent is on.
Fixed Out-of-schema option keys (e.g. a module's stored entries) are preserved across schema-driven saves, preventing silent data loss.
Fixed media fields validate that the value is an image URL, so a non-image/malformed URL can't be stored and render as a broken image.

White-label

Fixed The "footer credit" and "hide help links" controls now actually take effect (on the Help & Support panel) instead of being inert.
Fixed A deleted/404 brand-logo image falls back to the built-in mark instead of showing a broken image.

Migration

New One-Click Profiles and Save & Share surfaced in the Migration panel, with a friendlier import/preview UX.
Fixed Only enabled source-plugin settings are counted and imported.

Reliability

Fixed Module REST callbacks can no longer leak a database error, stray output, or an uncaught exception into a JSON response (which previously broke a panel with "Unexpected token '<'"); errors are contained and logged, and the response stays valid JSON.

Admin UX

New Opt-in usage analytics (WP Insights). Nothing is sent without explicit consent; helps prioritize what to build next.
Improved Sidebar grouping cleanup, conditional Pro ordering, and deep-link/scroll behavior for submenu navigation.
Improved Pro upgrade links now point to the pricing page.

Pro (requires xSpeed Cache Pro)

New Predictive Cache Warming and Scheduled Cache Prewarming are wired into the dashboard, warm your hottest or about-to-be-popular URLs on a schedule.
New Brotli compression (served where supported, GZIP fallback) via the new compression extension seam.

v1.0.5

2026-06-18

Migration into Free, white-label onboarding, LiteSpeed cache ownership & accurate hit counting.

Migration

New One-click migration from other caching plugins (LiteSpeed Cache, WP Rocket, W3 Total Cache, etc.) is now part of the Free plugin, import your existing exclusions and settings on activation instead of starting from scratch.

LiteSpeed

Fixed On LiteSpeed/OpenLiteSpeed, xSpeed Cache now tells LSCache to stand down (X-LiteSpeed-Cache-Control: no-cache) and owns the cache itself, so the X-XSpeed-Cache header is emitted, hits are counted, and the dashboard no longer falsely reports a PHP fallback.
Fixed LiteSpeed cache hits route through the drop-in (which both tags and counts them) since OpenLiteSpeed's .htaccess can't tag or log a static hit, giving consistent ~1ms hits and an accurate hit ratio.

Cache hit counting & stats

Fixed Hit/miss counters moved off transients onto a persistent option, so they no longer evaporate when a non-persistent object cache (e.g. an unreachable Redis) is active. The hit ratio was getting stuck at a fake 0%/100%.
Fixed Cache MISSes are now recorded inline so the hit-ratio stat reflects reality instead of being pinned at 100%.
Fixed PHP-served cache HITs are counted correctly and the drop-in device-bucket desync is resolved.
Fixed Homepage now caches via the static rewrite (the rule used a pattern that required a non-empty path, so / fell through to PHP while inner pages were rewritten).

Nginx

Fixed A nginx access_log directive in the generated snippet could take down the whole server when its log file was missing; the path is now resolved lazily so a deleted hits.log can't fail nginx -t.
Fixed The dashboard's nginx server-block snippet now updates optimistically when you toggle cache, instead of showing the pre-toggle state, and the wizard's Done step shows the post-apply block.

Admin UX

New Collapsible sidebar groups for cleaner navigation.
Improved Renamed the "Cache" module label to "Page Cache" for clarity.
Improved Sidebar group icons and chevrons brighten correctly on hover (white in dark mode).

Module fixes

Fixed Lazy Load, four correctness bugs resolved.
Fixed Heartbeat, editor-context detection, CLI set support, and honest frontend copy.
Fixed Database cleaner, expired-transient cleanup gaps and a count mismatch.
Fixed Google Fonts, no longer double-appends display=swap on entity-encoded hrefs.
Fixed Settings now strictly validate boolean fields instead of casting, preventing bad values from silently becoming true/false.
Fixed Object Cache, core option groups marked non-persistent so the drop-in can always be deactivated; degraded backends detected honestly.
Improved Static-rewrite SSL probe verifies the certificate and no longer blocks admin page loads.

v1.0.4

2026-06-14

One-click object cache, parity exclusions & admin polish.

Object Cache

New One-click Object Cache setup for Redis and Memcached: tests the connection, installs its own drop-in, and writes the wp-config constants (fully reversible). No drop-in plugin or PHP extension required.
Improved Dashboard now reports a degraded object cache honestly when the drop-in can't reach its backend, instead of implying caching is healthy.

Admin UX

New WP admin submenu now mirrors the in-dashboard navigation, so the menu and dashboard tabs stay in sync.
Improved Settings changes apply live across dashboard navigation, no full page reload needed.
Improved Menu icon now recolors to the active accent state correctly.
Improved Success notifications are anchored to a single consistent position (bottom-center).
Fixed Long panel titles no longer push the subtitle off-screen.
Fixed Number-input spinners render consistently across browsers (Firefox no longer clips the value).

Cache exclusions

New Exclusion lists now ship pre-populated with LiteSpeed / WP Rocket-parity defaults (16 URLs, 20 cookies, 28 query params), so a fresh install caches correctly out of the box.
New Exclusion rules now support regex via a ~ prefix (e.g. ~utm_[a-zA-Z0-9_-]+), alongside glob and substring, with ReDoS guards.

Bug fixes

Fixed Browser Cache no longer emits an "Array to string conversion" warning on multi-valued Cache-Control headers (also clears a false "nginx config required" notice).

License

Fixed Activating a Pro license now unlocks the Pro panels immediately, no full page reload needed.

v1.0.3

2026-06-07

Topology-aware UX, nginx HIT counting, admin polish.

Cache topology & UX

New Topology-aware rewrite banner: the dashboard now detects containerized hosts (xCloud, Kinsta, RunCloud Atomic, etc.) where the $document_root assumption doesn't hold, and tells the user exactly what to expect on their stack instead of silently failing.
New Unified nginx server-block snippet, one consolidated, copy-pasteable snippet (collapsible in the UI) replaces the previous fragmented sections.
New Nginx-served HITs are now counted, a dedicated access_log captures cache hits served directly by nginx (no PHP), so the dashboard "HITs in last 24h" stat is accurate on nginx setups.
New X-XSpeed-Cache response header: cache hits are now visible in the response headers, with a distinct value per serve layer (HIT (nginx) for the fast static path, HIT (php) for the drop-in fallback) so you can confirm a page was cached and tell exactly which layer served it.
Improved Browser Cache notice is topology-aware and renders its snippet in a proper code block.

Admin UX

New Third-party admin notices are suppressed on xSpeed Cache admin screens (page=xspeed* only), other plugins' "rate us" / promo notices no longer crowd the xSpeed Cache dashboard.
New Aligned sticky title-bar across the sidebar and content panels for a cleaner scroll experience.
Improved Browser Cache + GZIP notices probe-gate themselves, once the underlying issue is resolved, the notice dismisses on its own instead of lingering.

Benchmark

Fixed "Without cache" leg of the dashboard speed test now appends a cache-buster query string. Previously it was hitting the cache and reporting an artificially-fast baseline, making the speedup number look small.

v1.0.2

2026-06-02

Static-rewrite cache, Site Health & Fonts.

Static-rewrite cache + Site Health

New Static-file rewrite path, cached HTML is served directly by Apache / nginx / LiteSpeed, bypassing PHP entirely on cache hits (5-15ms TTFB vs ~85ms via the PHP drop-in).
New .htaccess static-cache block: installed automatically on cache enable, removed cleanly on disable. Block precedes WordPress's own rules so static files match first.
New nginx config snippet, copy-pasteable server { } block surfaced in the dashboard when nginx is detected (PHP can't write nginx config). Avoids the "if is evil" pitfall via a named-location fallback.
New LiteSpeed LSCache coexistence, xSpeed Cache detects LSCache's server-level module and steps back instead of double-caching.
New Active rewrite probe. Health module pings the cache directory and confirms the rewrite is actually serving static bytes (not just present in .htaccess).
New WordPress Site Health integration. Tools → Site Health now lists an xSpeed Cache check covering static-rewrite status + nginx config requirements.
New Persistent banner. Cache panel warns the admin when caching is on but the static-rewrite block isn't engaged (slow fallback path).
New Copy-to-clipboard button on every config-snippet panel (nginx, GZIP, object-cache).

Fonts

New Fonts module, adds font-display: swap to enqueued web fonts so visible text doesn't wait on a slow Google Fonts response, and exposes a preload list for above-the-fold font files.
New FontsModule tests covering the swap rewrite + preload <link> emission.

Improvements & fixes

Improved Server-type detection is cached so CLI / cron contexts see the same server type as web requests.
Improved Drop-in (advanced-cache.php) and WP_CACHE constant are preserved across plugin upgrades; auto-heal hook tightened to admin_init to avoid REST/cron noise.
Improved Plugin Check pass, i18n textdomains, WP_Filesystem coverage, SQL preparation, sanitization, and plugin/readme headers all cleaned up for WordPress.org review.
Fixed nginx snippet rewritten to avoid the try_files trap that broke pretty permalinks.
Fixed Rewrite condition normalized for trailing-slash + non-trailing-slash URLs.
Fixed WP-Rocket-style canonical pattern, server-level conditional rewrite.
Fixed Minify tag-rewrite filters bail in non-frontend contexts (REST / admin / cron).
Fixed wp.org release zip now ships vendor/, resolves the 1.0.1 activation fatal.
Improved Release pipeline rebuilt, .distignore-driven dist build, CI verify step, version-named artifact on every run.
Improved Plugin version read from the PHP header, single source of truth.

v1.0.1

2026-06-01

Foundation release, full feature set + Pro hooks.

Module architecture + LiteSpeed parity floor

New Module architecture. Every feature now ships as a self-contained Module (Cache, Health, Preloader, Heartbeat, Minify, GZIP, Lazy Load, Disable Bloat, Database, CDN, Cloudflare, Object Cache, Browser Cache).
New Health module, 24-hour hit/miss counter + activity log.
New Preloader module, sitemap-driven cache warmer with content-publish auto-warm.
New Cache exclusion intelligence, glob URL patterns, cookie patterns, User-Agent bypass, ignored query parameters.
New Per-device cache (mobile-separate).
New Per-post cache rules, don't-cache + custom expiry meta box.
New Minification. CSS / JS / HTML minify, combine, defer JS, delay JS, async CSS, remove ?ver= query strings.
New Lazy Load module, images / iframes / videos + auto CLS-fix.
New Disable Bloat module, 6 ergonomic toggles (dashicons, oEmbed, RSS, XML-RPC, jQuery Migrate, REST auth).
New Database module, optimize tables, scheduled cleanup, autoload analysis.
New CDN module, pull-zone URL rewriting.
New Cloudflare module, zone connect, auto-purge, dev-mode toggle.
New Object Cache module. Redis / Memcached config + status + flush.
New Browser Cache module. Cache-Control + Expires headers.
New Settings search across the entire dashboard with keyword highlighting.
New 3-step setup wizard on first activation with preset chooser and benchmark.
New Sidebar grouping under domain headers (Cache / Performance / Network / Insights / Tools).
New Sidebar tooltips + search shortcut in the collapsed rail.
New xspeed_branding filter. Agencies can rebrand the dashboard.
New xspeed_cache_skip_for_post + xspeed_cache_expiry_for_post filters.

Pro-essentials

New xspeed_module_descriptor filter. Pro hooks this to swap its panels to LicenseLockedPanel when license is invalid.
New AI Privacy module. GDPR off-switch + xspeed_ai_can_collect_data filter that Pro AI features must consult before recording visitor data.
New Pro upsell teasers, in-context inline cards on Cache, Minify, Lazy Load, Browser Cache and Disable Bloat panels.
New Locked Pro module rows in the sidebar, shows what Pro offers with a clear upgrade prompt.
New Pro Audit on the Cache panel, site-specific scan listing the top Pro features that would help THIS site, with severity chips and concrete reasons (not generic marketing copy).
New Sidebar slot for the license module (appears when xSpeed Cache Pro is installed).
New Global 36px form-control height baseline across the dashboard.
New filemtime() cache busting on admin asset URLs.

Improvements & fixes

Improved React panel registry, modules auto-render in the dashboard.
Improved Portal-based save indicator, zero layout shift.
Improved Distribution zip prunes dev dependencies (composer install --no-dev).
Fixed 5 duplicate module icons + regression test.

v1.0.0

2026-05-27

Initial release.

xSpeed Cache Pro

v1.3.2

2026-10-12

A failed image pass no longer serves an empty page, and each cache miss reads far less stored page data.

Image Optimization

Fixed When the WebP picture pass fails on a page, the page is served without it instead of empty.

Reliability

Improved A cache miss reads one sixteenth of the stored page facts instead of all of them, and autosaves no longer touch them.

v1.3.1

2026-10-08

Cloudflare Enterprise setup is now four short steps with a card for each DNS record, opens right after activation, and waits for an active Pro licence.

Cloudflare Enterprise

New Setup runs in four steps: Setup, Verify, Connect and Done. Each step has one short instruction, the records to add and a status line that checks on its own.
New Each DNS record has its own card with a Copy button beside every value. Where the root domain can take a CNAME or A records, you pick one, and the card opens on the one your domain uses now.
Improved After the add-on key activates, the Cloudflare Enterprise page opens and says the licence is active. Without an active Pro licence, it asks for the Pro key first.
Improved While the DNS records are on their way, the panel shows a waiting card, checks again every few seconds, says when it takes longer than usual, and offers a way out after 10 minutes.
Improved A problem says what is wrong in plain words, in the plugin's usual warning style, with Check DNS again beside it and the details one click away.
Improved The setup page shows the add-on's price as the service reports it.
Improved The header reads "Setting up" during the DNS steps, and the sidebar offer stays away meanwhile.
Improved The Cloudflare chip is gone from the top bar. The page header and the setup steps say where things stand.
Improved The licence use card shows during setup only when the licence has no site left.
Improved The panel links the setup guide and your DNS provider's instructions, and the steps are shorter.
Improved The sidebar offer uses the free plugin's card, so the two look and resize the same.
Fixed Setup cannot start while the Pro licence is inactive, from the dashboard, WP-CLI or MCP.
Fixed "Activate the license" on the two-licence screen opens the Pro licence card, not the add-on's.
Fixed Licence changes show on the page without a reload.
Fixed If Cloudflare stops serving pages part-way through setup, the Connect step stays open and names the problem.
Fixed Enabling the domain no longer flashes back to the enable screen.
Fixed When an activated key does not save, the licence card says so and what to do, instead of showing "valid" over an empty form.
Fixed On a subdomain site, the DNS step names each record by the site's own hostname.

v1.3.0

2026-10-07

Cloudflare Enterprise arrives as an add-on: the site's pages are served and purged from Cloudflare's enterprise edge, set up from one panel in wp-admin. Measured hero images are preloaded per device, and a phone copy counts as warm only once it is cached.

Cloudflare Enterprise

New A Cloudflare Enterprise add-on with its own licence, sold beside Pro. One panel walks through enabling the domain, the DNS records each name needs, and when the site reaches the edge.
New The panel shows usage, where the edge fetches pages from, and the lifetime Cloudflare uses. Bandwidth warnings appear at 80% and 90%.
New Purge All, a post save and a manual purge reach Cloudflare. A purge the service cannot take yet is kept and retried, and visitor-triggered purges are sent at most once every 10 seconds.
New On sites that bought Cloudflare Enterprise from xCloud, the panel says the edge is managed by xCloud, and purges go through xCloud's purge plugin.
New A Cloudflare status chip in the top bar, and a recovery screen when a domain was removed or the licence lapsed.
Improved The edge never keeps a page longer than the page cache does, and a Custom Rule's lifetime reaches the edge too.
Improved The CDN module and a second Cloudflare proxy stand down while the edge is on.
Fixed Turning the module off purges the edge, and a lapsed licence keeps the site served while the panel says what to do.

Image Optimization

New The hero image the rendering service measured is preloaded, for each device separately.
Fixed The image rewrite is suspended behind an edge that ignores Vary, so visitors never get an image format their browser cannot show.
Fixed The .htaccess image block is written once WordPress has loaded, and a block saved with Windows line endings counts as current.

Critical CSS

Improved A CDN is told to wait while a page's Critical CSS or Unused CSS is still missing, so it does not keep the unoptimized page.

Warming

Fixed A page counts as warm only when its phone copy is cached too, and a phone copy that can never be stored no longer holds the warmers back.
Fixed Warming finds pages whose address uses non-Latin characters, however the address is spelled.

Real User Monitoring

Fixed Refused beacons say why, and a site can name the other hosts it serves from.

Reliability

Fixed Pro's panels register even when Free's module registry loads late.
Fixed A licence change clears the cached licence answer at once.
Fixed Maintenance Cache's launch purge reaches the edge.
Fixed Dashboard requests work on sites whose REST address carries a query string.

v1.2.7

2026-10-01

Critical CSS is smaller and says when it is still large, collapsed elements in the first screen stay in the fold, and deactivating Pro no longer switches off Free's features.

Critical CSS

Improved Critical CSS trims selector groups and drops repeated rules, so it is smaller without changing what it styles. A result over 50 KB now comes with a warning in WP-CLI and over MCP.
Fixed An element collapsed in the first screen, such as an animation's zero-size start state, is kept in the fold when the browser measures it, matching the rendering service.

Reliability

Fixed Deactivating Pro while Free stays active now stops only Pro's modules. Free's Browser Cache rules and scheduled cleanups and purges stay in place.

Dashboard & Admin UX

Improved Settings labels and hints are rewritten in plain language and sentence case.

v1.2.6

2026-09-28

Critical CSS now takes effect the day it is measured instead of waiting for visitor confirmation, fold blobs carry only the font variants the fold uses, and Unused CSS can no longer be poisoned by a cache answering the generator with an already-optimized page. SmartPredict now sets how WordPress prefetches or prerenders the next page.

SmartPredict

New The SmartPredict tab configures the speculative loading tag WordPress 6.8+ prints: prefetch or prerender, when loading starts (on click, on hover or eagerly), paths never to prefetch such as /cart/*, and paths always to prefetch. These work with SmartPredict tracking off and need no traffic history. Logged-in visitors stay excluded, as in core.

Critical CSS

New A fold measured in a real browser licenses full stylesheet deferral immediately. Visitor fold reports keep collecting and still rebuild the blob from real-audience geometry at quorum — they guard the fold now instead of gating it. A filter restores the old wait for sites that prefer it.
Improved The fold blob keeps only the font faces whose weight and style the fold's own rules use, drops faces whose unicode-range covers no character on the page, and no longer carries @import statements — so large folds fit the store instead of arriving truncated and losing their deferral licence.
Fixed Every page no longer shares one fold: blobs are stored per page template, the landmark-less fold estimate is bounded, and an upgraded site stops serving another page's CSS from the old shared seat.
Fixed A manual Purge All no longer discards the visitor fold evidence — purging caches does not change pages, so the evidence stays.

Unused CSS

Fixed The generator refuses to build from a page that already serves its own pruned CSS — the state a front cache can hand back — instead of silently re-pruning its own output into an entry no rebuild could ever heal.
Fixed A rebuild the plan rejects is quarantined so visits stop re-queuing it, a revision save no longer hands back the day's retries, and self-heal counters are kept per page.

Rendering Service

New Scheduled CSS builds now render through the Hub's job queue instead of holding a request open — the site submits a page, gets on with its day, and collects the finished measurement.
Improved One render now serves both Critical CSS and Unused CSS, query-string variants of a page share a render instead of each spending one, and a failure pauses only its own class of work rather than the whole queue.
Improved The rendering service's visits identify themselves as the site's own traffic, so they no longer count as visitors or trip firewall rules.

Cloudflare

Fixed The APO module's setting now says what it does — it sets the browser cache TTL, not an edge TTL.

v1.2.5

2026-09-22

The AI Provider card now says what the API key is actually for, and that connecting Claude does not need one.

AI

Fixed The AI Provider card explained itself as the prerequisite for connecting Claude, which it is not. It now names the providers it accepts, the Pro features the key powers, and points to MCP Server — free, and no key required — for connecting an AI assistant.

v1.2.4

2026-09-20

Critical CSS is built per template from validated requests only, licensing reads the right key, and Cloudflare APO tells "not connected" apart from "refused".

Critical CSS

Fixed Builds are gated on request validity and bucketed per template, so a feed, embed or query-string URL can never seed a page's Critical CSS.
Fixed Critical CSS bootstraps correctly when the Unused CSS strategy is active, runs are spliced by offset, and the measured URL is trimmed of stray whitespace.
Fixed Run-level deferral now obeys the fold license ladder.
Improved The below-fold render-skip moved to the Free plugin, and it stands down during CSS measurement renders so measurements see the full page.

Licensing & Reliability

Fixed License status reads the option key the licensing library actually writes, so a valid license is always recognized.
Fixed The "why Pro is inert" notices now reach network admin too, and a partly deleted install can no longer take the site down.

Cloudflare APO

Fixed The panel tells "not connected yet" apart from "Cloudflare said no", and a failed Refresh keeps the last good answer instead of dropping it.

v1.2.3

2026-09-16

The CSS pipeline stops wasting renders — and the edge waits until a page is actually finished being optimized.

Critical CSS & Unused CSS

Improved A page whose Critical CSS is being rebuilt keeps serving its previous copy instead of going unoptimized.
Fixed Feeds, embeds, favicon.ico and other non-page URLs are no longer queued for CSS generation — and events queued before the fix are dropped for good on upgrade, ending the endless retry loop.
Improved Unused CSS payloads now live on disk with only metadata in the database, keeping the options table lean.

Edge & CDN

New The CSS modules now report when a page's optimization is still pending, so the edge is never primed with a half-optimized copy.
Fixed A URL with no fold to measure, or whose build was capped or kept failing, no longer holds the edge off indefinitely.

v1.2.2

2026-09-15

Critical CSS generation heals itself when a run's files go missing, and small stylesheets are no longer held back while the fold is unconfirmed.

Critical CSS

Fixed A UCSS run whose stored files went missing now regenerates itself instead of failing silently, and small stylesheets are inlined even before the fold is confirmed.

v1.2.1

2026-09-14

The front-end beacons are minified at build time instead of shipping as source, cutting what every visitor downloads on an uncached page view from 29.9 KB to 8.7 KB. A Cloudflare APO panel that has not been set up yet reads as a setup step rather than an error, and Pro panels render correctly in dark mode again.

Optimization

Fixed The CSS, fold, RUM and smart-predict beacons are minified into the shipped assets — 71% off what a visitor downloads, and no longer flagged as unminified JavaScript by external audits. The readable sources stay in the plugin for review.

Cloudflare APO

Fixed A status probe that never reached the Cloudflare API — no zone configured, missing credentials, a transport failure — is shown as an info callout pointing at the Cloudflare module. The danger callout is now reserved for real API rejections.

Reliability

Fixed Pro panels no longer render as white boxes in dark mode. A build step that supplies the list of Pro-only styles to Free had been dropped, so those styles were purged from the stylesheet.

v1.2.0

2026-09-13

Critical CSS now builds itself, the way Unused CSS already does, and both use the fold a real browser measured instead of counting opening tags. Licensed installs generate in the cloud first and say so when the cloud fails, rather than silently falling back to a local build. Converted images that came out larger than the original are no longer kept or served.

Critical CSS & Unused CSS

New Critical CSS builds on its own when pages change — no button to press. The screens that suggested otherwise now say builds are automatic.
New The fold is taken from what the renderer actually measured, replacing the inline byte budget and the tag-count approximation.
New Licensed installs generate in the cloud first, and a cloud-render failure is surfaced instead of silently building locally.
Fixed Deferring every stylesheet now waits for a real visitor's fold to confirm it, and a fold cut short by the size cap no longer licenses deferring everything.
Fixed Pages with only inline styles now emit their fold, and a measured fold can defer the remaining sheets.
Fixed Purge All no longer destroys the generated CSS along with the page cache.
Fixed An unwritable Unused CSS run directory is reclaimed instead of failing every run, and the inline fallback is bounded.
Fixed A generated block is capped at a rule boundary, skips its cooldown when asked, and is gated by fingerprint so identical pages don't rebuild.

Image Optimization

Fixed A WebP or AVIF that came out larger than the original is no longer kept or served, oversized copies are reported instead of deleted, and the audit says when conversions lost.
Fixed The LCP preload is no longer rewritten to a sibling size the page never requests.
Fixed Cleanup respects the license, an absent settings row means the defaults rather than nothing, and kept markers clear on the first save too.

Multisite

Fixed Purging all sites validates every blog id, names the sites that failed and keeps that message after the panel reloads, and judges success by whether the caches actually went — including page builders' own render caches.

AI

Fixed Every OpenAI model works again, whether it takes the old token parameter name or the new one.

v1.1.4

2026-09-07

Unused CSS no longer waits on Critical CSS to defer, so the two features stop blocking each other, and Critical CSS now fits the fold to its budget instead of refusing outright. The AI provider catalogue covers current model generations.

Optimization

New Critical CSS fits the fold to the available budget rather than refusing when it does not fit, and stays fast doing it.
Fixed Unused CSS defers stylesheets without waiting on a Critical CSS blob, so either feature works on its own.
Fixed Stylesheets are rewritten anywhere in the document, not only in the head, and pruned CSS is generated for the whole document.
Fixed A font declaration nothing kept asks for is dropped, matched by brace rather than by pattern so only top-level rules are touched.
Fixed A Critical CSS refusal now says what it actually means.
Improved Pages are measured in a real browser before pruning, when one is reachable.

AI

Improved The model catalogue covers current generations, and a saved model the catalogue no longer lists still displays.

Licensing

Fixed Unused CSS proves the install with its Pro licence rather than a Hub pairing token, and sends the real key rather than the masked one.

Reliability

Fixed The CSS beacons no longer run during page load.

v1.1.3

2026-09-02

Every Pro AI feature works again. The API key was being sent to the provider still encrypted, so all four providers rejected it. Critical CSS and Unused CSS now take effect the moment you clear them, keep the files you uploaded through automatic rebuilds, and can no longer be generated or stored on a site without a licence.

AI

Fixed Every Pro AI feature failed to authenticate. The saved API key is stored encrypted, and it was handed to the provider still encrypted, so all four providers rejected it as an invalid key.

Critical CSS

Fixed Purging Critical CSS or Unused CSS now takes effect immediately. Clearing the stored CSS left the already-cached pages serving the old styles inlined in their markup, so nothing changed for visitors until the cache expired on its own.
Fixed A stylesheet you uploaded yourself is now kept when the plugin rebuilds automatically. Routine invalidation discarded it along with the generated files, so an uploaded file had to be re-uploaded after any change that triggered a rebuild.
Fixed Generating, uploading and capturing CSS now require a licence. Those routes could be reached through the API, WP-CLI or the AI tools on a site with no licence, while the dashboard showed the feature locked. Reading and clearing stay open on purpose.
Fixed The measurement now compares against the unoptimized page, so the reported saving reflects what the feature actually removed.
Fixed Stripping no longer runs when there is nothing to strip, and the site's own CDN address is used instead of being ignored.
Fixed Entries stored by earlier versions survive an upgrade rather than being guessed at or discarded.
Fixed The public reporting routes now require a licence.

Multisite

Fixed "Purge All Sites" now also clears caches held by page builders and other plugins that render their own output, instead of only xSpeed's.

Health

Fixed When another plugin owns the page cache, the recommendation now names that plugin instead of blaming file permissions and sending you to check file modes on a healthy filesystem. A host that ships wp-config.php read-only is no longer told the step failed when it actually succeeded and left a line to paste.

v1.1.2

2026-08-31

Brotli-compressed pages are now written for both cache paths and published atomically, so a compressed page can no longer arrive half-written, and cached pages carry the Pro version alongside Free's.

Compression

Fixed Brotli-compressed pages are now produced for both of xSpeed's cache paths, not only the one the web server reads directly. The PHP path never had a compressed file to find, so it could never serve Brotli at all.
Fixed A compressed page is published in one step rather than written in place. A crash, a full disk or a visitor arriving mid-write previously left a truncated file that no browser can decompress: a blank page, and sometimes a navigation that never finished. Readers now see either the previous complete file or the new one.
Fixed Each compressed page is now stored with its own length, so one that arrives cut short is skipped and the normal page is sent instead. Compressed copies made before this update carry no length and are still used as before; clearing the cache replaces them.

Caching

New Cached pages now carry the Pro version alongside Free's in the page signature, so an external scanner can tell the two editions apart. A white-label build removes the signature entirely rather than leaking the product name into page source.

v1.1.1

2026-08-27

Unused CSS is now measured in a real browser instead of inferred, the external generator endpoint is gone, and an incomplete Pro folder no longer takes every request down with it.

Critical CSS

New Unused CSS is measured by loading the page in a real browser and recording which rules the page actually applies, instead of inferring it from the markup. Rules a script or an interaction brings into use are seen as used, so styles the previous method removed are now kept.
Improved The generator endpoint and its API key have been removed. Both CSS features now measure the page in your own browser or on your own server; there is nothing to point an external service at, and an address that was not a web address used to be accepted here and then silently ignored. Any endpoint you had configured is no longer used.
Fixed The "Never prune these selectors" box on Unused CSS now appears. The setting worked, but the panel had no field for it, so the only way to add a selector was WP-CLI or a filter.
Fixed A relative url() in a stylesheet: an icon font, a background image, no longer breaks when its rules are moved into a combined file or inlined into the page. The reference is rewritten to still point at the original file.
Fixed A stylesheet reached through a query string or an @import is now resolved rather than skipped.
Fixed Interaction states are measured across every control the probe opens, not only the last one left open, so styles that appear on hover or click are no longer dropped as unused.
Fixed A scan that runs out of time is discarded rather than saved half-finished, which previously removed styles the incomplete scan never got to see.
Fixed Captured CSS state is no longer discarded when a language pack or an unrelated plugin is installed.

Compression

Fixed Enabling Brotli on a server without Brotli support no longer reports plain success. The tools that flip the setting now report the same warning the dashboard shows, instead of logging a change that has no effect on what visitors download.

Caching

Fixed The page cache is cleared when Pro itself is updated, so a page is never served from markup the previous version produced.

Reliability

Fixed A missing Pro file no longer takes down every request. Pro stops cleanly and names what is missing, leaving the site and wp-admin usable so the plugin can be reinstalled.
Fixed A Pro build paired with an older Free version now stops with an explanation instead of fataling on the first Free function it expects and does not find.
Fixed An incomplete Pro install no longer breaks the screens that ask which features are active, they now answer correctly instead of failing on the module the broken install is missing.

v1.1.0

2026-08-24

Requires xSpeed 1.2.0 or later. A security fix for stored CSS that could break out of the block it is inlined into, and the Apply button on a Pro recommendation now works. Unused CSS no longer strips stylesheets it should have left alone, and CSS entries are keyed per page rather than shared across pages that only differ by query string.

Security

Fixed Stored CSS can no longer terminate the style block it is inlined into. An HTML parser ends that element at the first "</style" in any case, followed by anything: so CSS containing that sequence closed the block early and everything after it was parsed as markup rather than styles, which could run script on every page that served the entry. The escape matches what a parser actually looks for rather than the literal closing tag, since "</style bogus>" and a newline before the ">" close the element just as effectively. Nothing legitimate is affected: "</style" is already a CSS parse error.

Recommendations

Fixed The Apply button on a Pro recommendation works instead of failing silently. Free and Pro name their recommendations differently, and only Free's names were understood by the button both of them share, so every Pro Apply failed and the error never reached the screen.
Fixed A recommendation that no longer applies now says so, instead of reporting the same failure as one that could not be applied at all.

Unused CSS

Fixed One expired entry no longer causes every stylesheet on the page to be stripped. A single bad entry took the whole page's CSS with it.
Fixed Stylesheets are replaced in contiguous runs and in place, so the cascade order they were enqueued in is preserved and nothing is hoisted past the rules that override it.
Fixed Only one CSS strategy resolves per request, so Critical CSS and Unused CSS no longer both act on the same page.
Fixed A run entry no longer duplicates what it stores, and what it keeps is bounded.
Fixed Entries written before the key change are re-filed on read rather than silently ignored, and an entry that is refused now says why.

Critical CSS

Fixed Entries are keyed on the routed path plus the query parameters that actually select content. Pages differing only by a tracking parameter previously shared one entry, so one page's CSS was served for another.
Fixed Ignored query parameters are matched by whole name rather than as substrings.
Fixed Generation fetches the unoptimized page, so stored CSS reflects the real stylesheet rather than an already-optimized copy.

v1.0.10

2026-08-20

A security release. The Real User Monitoring endpoint and the predictive tracker were both open to anonymous callers with no bound on what they could store, network-wide multisite settings could be changed by a single site's administrator, and the licensing library carried an update-channel exposure.

Security

Fixed The Real User Monitoring beacon no longer accepts data from anonymous callers when the feature is switched off, and what it accepts is bounded. The endpoint is public by necessity. It receives measurements from visitors' browsers: but it stored whatever arrived, in unlimited quantity, whether or not RUM was enabled. It now returns "not found" when disabled, caps each batch, keeps one entry per metric name, and rejects measurements attributed to another site's URLs.
Fixed The predictive tracker only accepts page transitions that belong to this site. It previously recorded any URL a caller sent, so an anonymous request could place an arbitrary address into the prediction data, and from there into the speculation rules the site prints for browsers to prefetch. The host is now checked when the transition is recorded and again when the rules are rendered, so anything already stored is filtered on the way out.
Fixed The predictive tracker is rate-limited, so a single caller can no longer grow the stored prediction data without limit.
Fixed On a multisite network, changing settings that apply to the whole network now requires a network administrator. The routes checked manage_options, which an individual site's administrator holds, so one site's admin could change settings affecting every site. Off a network the check falls back to the site capability, so single-site installs are unaffected.
Fixed The licensing library moves to 2.3.1, closing an exposure in its update channel.

Predictive warming

Fixed The tracker reports what it actually recorded. It inferred success by comparing the buffer size before and after, but the buffer is capped, once full the count stops changing, so on any site busy enough for the feature to be worthwhile it reported "ignored" for every transition, including the ones it had just stored.
Fixed Sites behind a reverse proxy or CDN no longer share one rate-limit counter. Where the proxy does not restore the visitor's address every visitor looked like the same caller, so the site stopped collecting transitions once the shared counter filled. An xspeed_smart_predict_client_ip filter lets a site point the limiter at whichever header its infrastructure sets.

Interface

Fixed A failed save no longer shows the green "Settings saved" toast, and the failure stays visible after the toast fades instead of disappearing with it.

v1.0.9

2026-08-17

Predictive warming now recognises pages that are already cached, instead of re-warming the same ones on every run.

Predictive warming

Fixed The warmer now finds pages the cache has already stored, so "skip pages that are already fresh" works again. It was looking in the wrong place after the free plugin moved cached pages into per-site folders, so every page read as cold and each run spent its whole budget re-warming pages that were already warm.

v1.0.8

2026-08-13

Pro settings are no longer writable on a site whose licence has lapsed, a PageSpeed run from an assistant is finally recorded, and Pro toggles are keyboard-navigable again.

Licensing

Fixed On a site without an active licence, Pro settings can no longer be changed through WP-CLI or an AI assistant. The dashboard already showed those panels locked, but four write routes and the image recommendation bypassed the check entirely, a change made that way was saved and reported as successful.
Fixed A refused change is now reported as one. It previously returned success over settings it had never written, both in the REST response and in the command's exit code, so a script could carry on believing a change had landed.

Speed test

Fixed A PageSpeed run started from an AI assistant is now recorded in the site's run history. It previously ran, returned a score, and stored nothing, so the history the assistant points you at stayed empty. A cached re-read still records nothing, since it is not a new measurement.

Accessibility

Fixed Toggles in Pro settings panels show a focus ring again when reached by keyboard. The indicator disappeared entirely on reaching a toggle, so anyone navigating by Tab had nothing showing which control was focused and pressing Space was a guess. Free's toggles were unaffected, and the two sit side by side on the same screen.

v1.0.7

2026-08-10

Edits are no longer lost while a panel saves, failed image conversions are counted, and the Brotli snippet reaches the nginx users who need it.

Settings & Admin UX

Fixed Anything typed while a Pro panel was saving is no longer overwritten when the save lands. The value on screen is now what gets stored, on all nine panels.
Fixed A "Save failed" message on the Maintenance Cache panel now clears once the next save succeeds, instead of staying on screen indefinitely.

Images

Fixed Bulk conversion now counts failures. A library where every AVIF encode failed previously reported the same green "Done: 0 new file(s) converted" as one that was already fully converted, with no signal anywhere that something had gone wrong. A run that converted nothing but hit failures is now shown in amber, and wp xspeed images bulk --now warns instead of reporting success.
Improved The progress readouts say which unit they're counting. Attachments and files were previously reported as one number, so the running line could look like a counter that had overrun its own total.

Compression

Fixed On nginx, the Brotli snippet is now shown even when Brotli isn't active yet. That snippet is what tells you how to turn it on, so gating it on the thing it enables meant the users who most needed it never saw it.
Improved A detection check that can't complete now says so, and names the likely causes, instead of reporting Brotli as unavailable.

CSS

Fixed Deferred stylesheets now emit valid markup, and are no longer processed twice when Free's Minify has already deferred them, which previously produced duplicate handlers and a no-JS fallback that didn't fall back.

Warming

Fixed One-off prewarm times are read in your site's timezone instead of UTC, so a warm set for 3:00 PM runs at 3:00 PM. A one-off that genuinely will not fire is now flagged, and one that is merely due is no longer mislabelled.

Licensing

Improved The license notice in wp-admin now uses the same colours, spacing, and icon as the dashboard, instead of its own palette that read as a different plugin's notice.
Improved Agency branding still overrides the notice accent, so a white-labelled install keeps its own colour.
Fixed The deactivation dialog no longer promises a 7-day grace window that deactivation never gave. It now says Pro stops immediately and your key is freed for another site.

AI / MCP

Fixed wp xspeed ai status reports the configured provider key instead of "(unset)", and no longer emits a PHP warning.

v1.0.6

2026-08-05

Unused-CSS removal now works out of the box, and a fatal-error fix for sites running the latest Free release.

Reliability

Fixed With this release's Free version active, the site could fail to load entirely. Compatibility with the updated Free plugin is restored.

Unused CSS

New Unused-CSS removal now works without any external service. Stylesheets are pruned on your own server, so the feature runs on a default install instead of needing a generator endpoint.
Improved A configured generator endpoint still takes priority, and the result now names which method produced it.
Fixed Stored CSS is no longer cut mid-rule when it hits the size cap, which could leave part of a page unstyled.

Settings & Admin UX

Improved License and Branding now have distinct icons and labels on the Settings screen.

AI / MCP

Fixed Unrecognised commands for images, critical CSS, unused CSS, and migration now report an error instead of silently succeeding.

v1.0.5

2026-07-30

Image-wrapping and licensing fixes, plus more reliable real-user metrics.

Image Optimization

Fixed Wrapped images no longer receive max-width and height overrides that could distort their sizing.
Fixed Logo links are no longer wrapped in a picture element, which could break header layouts.

Licensing

Improved A failed license activation now explains what went wrong and what to do next, instead of failing silently.
Fixed The "What Pro adds" link now opens the Features page.

Performance Monitoring

Fixed Real-user metrics are no longer discarded when the metrics table is missing. It is recreated automatically.
Fixed The metrics beacon is now served from your own site rather than an external host.

v1.0.4

2026-07-27

License activation now connects to the production WPDeveloper store.

Licensing

Fixed License activation and validation now connect to the production WPDeveloper store instead of the pre-launch staging endpoint.

v1.0.3

2026-07-15

Maintenance release with build and release process improvements.

Reliability

Improved Build and release pipeline for more reliable and consistent Pro packages.

v1.0.2

2026-07-13

Bulk image optimization, AI integration, and licensing improvements.

Image Optimization

New Bulk WebP and AVIF conversion for existing media libraries.
New Background image conversion with live progress and storage statistics.
New Configurable output format selection for WebP, AVIF, or both.
Fixed Improved WebP and AVIF delivery for cached pages.
Improved Better image optimization settings and panel experience.

AI / MCP

New MCP support for all Pro modules, enabling control from Claude and other MCP-compatible AI assistants.

Licensing

Improved Enhanced Free and Pro license state detection for more accurate dashboard messaging.

v1.0.1

2026-07-02

Maintenance release with image delivery, cache purge, and migration improvements.

Image Optimization

Fixed Improved WebP and AVIF delivery, including support for CSS background images.

Caching

Fixed CSS optimization cache is now properly cleared during cache purges.

Migration

Fixed W3 Total Cache importer now supports Redis ACL credentials.

v1.0.0

2026-06-25

Initial release of xSpeed Cache Pro. Built as an add-on for xSpeed Cache Free, installs alongside Free and layers 25+ Pro modules into the same dashboard, gated by a single license.

Caching

New REST API Cache. Cache read-only REST responses with a TTL you set per route; built for headless / app back-ends.
New Feed Caching, cache RSS / Atom / comment feeds (with correct content-type) so aggregators polling your feed skip a full render.
New 404 Caching, serve a single cached 404 page so bot/scanner floods on nonexistent URLs don't hammer PHP.
New Search Caching, cache internal search-results pages (/?s=…) so popular repeated searches skip a full query.
New Custom Cache Rules, bypass cache or override expiry by URL, post type, category, tag, or author, with priority ordering.
New Maintenance-aware caching. Skip caching while the site is in maintenance / coming-soon mode and auto-purge when it goes live.

Performance

New Critical CSS, inline above-the-fold CSS and defer the rest, per template.
New Unused CSS, inline a pruned per-URL stylesheet and strip the originals; pairs with Critical CSS.
New Image Optimization, convert new JPEG/PNG uploads to WebP and AVIF and serve them to capable browsers.
New Smart Image. AI-recommended format + quality settings based on your media library.
New Adaptive Cache. AI-tuned cache TTL based on 24-hour traffic patterns.
New Predictive Cache Warming, proactively warm the hottest URLs, ranked by real traffic, recency, and content, on a schedule.
New Scheduled Cache Prewarming, warm target URLs ahead of scheduled moments (a post going live, a sale, a campaign) so the spike hits a warm cache.
New Smart Predict, predict the next page a visitor is likely to open and prefetch it.

Edge & Network

New Brotli Compression, serve Brotli-compressed responses where the browser and server support it, with automatic GZIP fallback.
New Cloudflare APO, toggle Automatic Platform Optimization, edge cache level, and TTL on your connected Cloudflare zone.

Insights & monitoring

New Real-User Monitoring (RUM), sample Core Web Vitals (LCP, FCP, CLS, INP, TTFB) from real visitors, charted per page and per device.
New Performance Health. Core Web Vitals health score with AI anomaly detection, reading the data RUM collects.
New PageSpeed, on-demand Google PageSpeed Insights audits; scores + top issues cached for 24 hours.
New Analytics, hit-ratio trends, slowest URLs (from RUM), and recent activity in one view.
New Recommendations, site-specific configuration advice grounded in the active modules, with one-click apply.

AI

New Pluggable AI provider. Choose OpenAI, Anthropic, or OpenRouter; powers Adaptive Cache, Smart Image, Smart Predict, Performance Health, and Recommendations.

Operations

New Migration, one-click importers from WP Rocket, W3 Total Cache, and WP Super Cache.
New Advanced Migration, host-tuned profiles, bulk/multisite import, and shareable Save & Share profiles.
New Multisite, network-wide cache control with per-subsite overrides and a network admin panel.
New White Label, rebrand the dashboard chrome (name, logo, footer credit, hide help links) for agencies.
New License, activate xSpeed Cache Pro via the WPDeveloper store with periodic revalidation and a license-locked panel fallback when invalid.

Integration with xSpeed Cache Free

New Layers onto Free's module registry. Pro modules reuse Free's schema-driven panels, stat cards, and form controls for one consistent dashboard.
New Pro REST routes return 404 from the outside when the license is invalid; the dashboard renders a license-locked panel in their place.

xSpeed Hub

v1.4.8

2026-10-12

Google One Tap on the website. xspeedcache.com can show Google's prompt to signed-out visitors and sign them in to their Hub account, through two new website-session endpoints with the same checks as the app's One Tap. The website's origin must be an authorized JavaScript origin on the Google client.

Added

New Google One Tap on the website. xspeedcache.com can show Google's prompt to signed-out visitors and sign them in to their Hub account, through two new website-session endpoints with the same checks as the app's One Tap. The website's origin must be an authorized JavaScript origin on the Google client.

Fixed

Fixed Switching back to the Hub tab no longer shows the loading logo, even on a slow connection. 1.4.7 hid the page after 800 ms; over a proxy or a long route the sign-in check takes longer than that. The page now stays on screen for the whole check and takes no clicks until it ends.
Fixed Clicking the page no longer closes the Google One Tap prompt. Google treats a close as a dismissal and holds the prompt back for hours, so a stray click hid it. It now closes only from its own close button.

v1.4.7

2026-10-11

Google One Tap sign-in. A browser already signed in to Google sees Google's "Continue as …" prompt on the sign-in page, and one click signs in, or creates the account the first time. Two-factor still applies. The hub verifies the ID token's signature against Google's keys and binds it to a single-use nonce. `GOOGLE_ONE_TAP=off` hides the prompt.

Added

New Google One Tap sign-in. A browser already signed in to Google sees Google's "Continue as …" prompt on the sign-in page, and one click signs in, or creates the account the first time. Two-factor still applies. The hub verifies the ID token's signature against Google's keys and binds it to a single-use nonce. `GOOGLE_ONE_TAP=off` hides the prompt.
New The Hub now offers every tool each site's xSpeed plugin publishes, not only the 29 it has its own copy of, and keeps up with the plugin by itself: a new plugin command, an update or a module switched on reaches AI clients with no Hub release. A read-only connection can still run a tool's read actions, and actions that can't be undone wait for the site owner's approval in wp-admin.

Fixed

Fixed Coming back to the Hub tab no longer reloads the page. Returning from another tab still re-checks who is signed in, but the page stays on screen and only stops taking clicks until the check ends. The boot logo now shows only if the check takes longer than 800 ms.

v1.4.6

2026-10-07

Each DNS provider's own how-to link. `dns_provider` carries `help_url`, the provider's page on adding a DNS record, for the providers whose page we could open. The plugin and the Cloudflare Enterprise tab show it beside the DNS settings link, with the setup guide.

Added

New Each DNS provider's own how-to link. `dns_provider` carries `help_url`, the provider's page on adding a DNS record, for the providers whose page we could open. The plugin and the Cloudflare Enterprise tab show it beside the DNS settings link, with the setup guide.
New Hostinger and Google Cloud DNS are recognised. Google Cloud DNS was read as Squarespace, because both serve from `googledomains.com`.
New Cloudflare DNS customers are told to set the new records to DNS only. (`proxy_must_be_off`). A proxied record puts their own Cloudflare zone in front of the edge and the setup fails.
New The enable answer says whether the records came. (`records_fresh`), and the new registration is watched at once, so the first DNS check lands within one live pass.

Changed

Improved The certificate step waits for the customer's records. while its `_acme-challenge` record is not answering, instead of counting "waiting 5 min · usually within 15 min" before anything was added.
Improved The tab uses the plugin's step names. ("Cloudflare confirmed you own the domain", "Security certificate ready", "Visitors reach Cloudflare", "Cloudflare serves your pages") and "Setting up DNS" in place of "Pending DNS".
Improved A stored provider reads its links and notes from the current map. , so a domain detected before this release gets them without waiting for a pass.

v1.4.5

2026-10-07

xCloud's visitor rate limit is switched off. xCloud enables it on every domain, and it challenged the Hub's own calls to a site's `/wp-json`. The Hub now writes `rate_limiting: false` on every domain it holds, in the same settings write as the cache lifetime mode. `XCLOUD_CFE_RATE_LIMITING_OFF=0` stops it.

Added

New xCloud's visitor rate limit is switched off. xCloud enables it on every domain, and it challenged the Hub's own calls to a site's `/wp-json`. The Hub now writes `rate_limiting: false` on every domain it holds, in the same settings write as the cache lifetime mode. `XCLOUD_CFE_RATE_LIMITING_OFF=0` stops it.
New The per-site purge budgets are off for now. Ordinary saves the Hub had widened to a whole-host purge used up the 10-an-hour budget in testing, and the plugin then held every purge until it cleared. The 2-second coalescing window and the account quota still apply. `XCLOUD_CFE_PURGE_BUCKETS=1` turns the budgets back on.
New Cloudflare page caching can be on from the start. A plugin that sends `page_caching: true` when it enables Cloudflare Enterprise gets page caching switched on once, in the same write that puts the edge on `respect_origin`, so the edge copies only what xSpeed caches. The request is kept on the registration and retried by the poller if the write fails. A customer who sets page caching themselves, on or off, keeps that choice for good. Nothing changes for a plugin that does not send the field, for registrations made before it, or with `XCLOUD_CFE_RESPECT_ORIGIN=0`. Two columns are added to `cfe_domains`, applied on boot.

Changed

Improved The Cloudflare Enterprise page for a site that is not set up yet is redesigned. (#351). It now matches the plugin: "You need two things" shows xSpeed Cache Pro and the Cloudflare Enterprise Add-on as two steps, beside the add-on's price and what it adds, with a "How it works" diagram below. The pill by the title and the steps follow what the site reports about its licences: "Pro and add-on needed", "Pro license and add-on needed" with an Activate License link, "Add-on needed", or "Ready to set up" with a link to start setup in the plugin. Activate License and the key link open the plugin's License page on the site. Run checks moves to its own "Check your domain and server" card and works as before. Every screen of the page now opens with the same header.
Improved The add-on's price comes from the store. The Hub asks WPDeveloper's store for it (cached for 12 hours) and shows "From" when there are several prices. When the store has not answered, no price is shown.
Improved The daily pass records each site's licences. It now reads the plugin's `get_site_info` and stores Pro's licence and the Cloudflare Enterprise add-on's beside `pro_active`; `/account/fleet` returns them as `pro_licensed` and `cfe_licensed`. A new route, `GET /sites/:id/licences`, returns them live with the add-on's price.
Improved Tool descriptions describe the tool, and nothing else. Sentences that told the assistant what to do (confirm before contacting support, run the object-cache test first, always share the scan link, try a dry run first) moved from the tool descriptions into the connection's instructions, which already carried most of them. The assistant gets the same guidance.

Fixed

Fixed Cloudflare Enterprise setup checks a subdomain site at its own name. xCloud writes a subdomain's record relative to the zone above it (`smoke` for `smoke.example.com`). The Hub read it against the site's hostname and checked `smoke.smoke.example.com`, so step 2 never passed.
Fixed Temporary sign-in checks now offer a retry with account controls hidden instead of showing a false sign-out. Confirmed expired sessions still return to sign-in.
Fixed The website session profile includes the same Gravatar address as the Hub, without exposing the email address.
Fixed `optimize_site` across several sites now asks first. The connection's instructions listed every tool that takes `site: "all"` except `optimize_site`, so an agent could optimize a whole workspace without the "this will touch all N sites" check. (#346)
Fixed A 401 from the MCP endpoint says where to sign in. It now carries `WWW-Authenticate: Bearer resource_metadata="…/.well-known/oauth-protected-resource"`, so a client that finds OAuth from the 401 alone can connect. (#344)
Fixed Tools now say which ones only read. Every tool carries `readOnlyHint`, and writes also say whether they are destructive. ChatGPT no longer asks before every read, and clients such as Codex now ask before a purge or a settings change. (#345)
Fixed Every tool has a readable title. `tools/list` now carries a `title` annotation for each tool, such as "Purge cache" or "Run PageSpeed test", which directories and clients show in their tool listings. (#345)
Fixed `run_benchmark` and `test_object_cache` no longer claim to be read-only. The benchmark warms the home page cache and records the run, and the object-cache test writes a probe key, so their hints now say they change something (but nothing destructive). Viewers can still run both. (#345)
Fixed OAuth discovery at the path-suffixed URLs. The deployment guide now has the nginx block that sends `/.well-known/oauth-*/xspeed/mcp` to the Hub instead of the dashboard, so clients that try that form first get the metadata. (#343)
Fixed A certificate stuck behind the domain's own DNS provider is named. When the delegation CNAME is in place but the domain's nameservers answer the certificate check with TXT values of their own, the certificate row now waits on `challenge_shadowed` and carries both sets of values, instead of sitting in `pending_validation` with nothing to say why. Seen with a Cloudflare zone set to DNS only while Universal SSL was issuing the zone's own certificate. Cloudflare DNS also gets the `zone_ssl_answers_dcv` provider note, and pre-flight says Universal SSL may need to be off during setup when the domain's DNS is at Cloudflare.
Fixed A Cloudflare Enterprise settings save that xCloud stored is no longer reported as a failure. When xCloud answers `cloudflare_unavailable`, it has saved the settings and only the push to Cloudflare failed. The settings routes now read the domain back, and when every requested key holds the requested value they answer `202 {domain, applying: true}` with no error on the row. The poller sends those settings once more about five minutes later. A read-back that fails or differs still answers the failure. Seen on lenzora.site, where six saves in a row reported an error while the edge went on to apply each one.
Fixed A Cloudflare Enterprise purge of more than 30 URLs clears what it says it cleared. It used to widen to the HTML tag purge, which misses pages with no `Cache-Tag`, so on a site reporting `tags_reliable: false` untagged pages stayed stale while the purge reported success. Such a site now widens to the whole host, and a path-scoped site sends its URLs in calls of 30 (up to 200; more answers `422 too_many_urls`). When a split send fails part way, the new `outstanding_urls` lists what no call cleared. Nothing changes with `tags_reliable: true`.
Fixed After a server move, the edge follows the site to its new server. When Cloudflare Enterprise is enabled or resumed, the Hub records where the site's request came from. Once the domain is active, it compares the answer through the edge with a direct one, and points the origin at the site's own server when only the direct answer is this site. An origin xCloud moves later is flagged. Clearing the origin while the domain is live answers `409 origin_required_while_live`. One column, `origin_check`, is added to `cfe_domains`, applied on boot. (#339)
Fixed A registration deleted in xCloud no longer blocks the name. When another site's row holds the domain, the Hub asks xCloud and releases the row only when a full listing shows the name is gone.
Fixed A DNS revert to the customer's server counts as restored. The revert watch graded the record against the origin, which for xCloud is a proxied name, so a restored record stayed `unknown`. It now also matches the pre-cutover snapshot. The staff list says "was live; no longer at xCloud" for a registration xCloud removed after it went live.

Security

Fixed Switching Cloudflare page caching on also makes the edge follow the site's cache headers. A Cloudflare Enterprise settings save that turns `edge_page_caching` on now carries `edge_ttl_mode: respect_origin` in the same write. Before, a save that arrived before the Hub had set that mode could switch caching on under xCloud's default, which stores pages the site marks `no-store` and pages carrying `Set-Cookie`, so one visitor's page could be served to the next. A save that asks for caching on under any other mode answers `422 page_caching_needs_respect_origin`. With `XCLOUD_CFE_RESPECT_ORIGIN=0` the save is sent as asked and logged.

v1.4.4

2026-10-04

The staff console has its own sign-in, and a second factor is required. Being signed in to the account app no longer opens the console. Staff ask for a sign-in link on the console (10 minutes, one use, and the same answer whether or not the address is staff), then confirm with a staff passkey, an authenticator app code or a recovery code; a staff passkey alone also signs in. Anyone without a factor, break-glass superadmins included, must add one before anything else and gets 10 recovery codes, shown once. The console session is its own cookie (`__Host-`, HttpOnly, SameSite=Strict), ends after 12 hours or 30 idle minutes, and gets a new id at every second factor. Wrong codes lock after five tries, for longer each time. Every state-changing console request must come from the console's origin. Adding or removing a factor needs a second factor from the last 10 minutes; deletions and impersonation from the last 30. Removing someone's staff access or changing their role ends their console sessions. Sign-ins, factor changes and used recovery codes are in the audit log, and factor changes and used recovery codes ring the bell for the person and for superadmins. The Profile page has a Security card for passkeys, the authenticator, recovery codes and console sessions. Set `XSPEED_HUB_ADMIN_URL` before deploying; a lost factor is reset on the box with `dist/ops/admin-auth-cli.js`. See [admin-auth](docs/architecture/admin-auth.md).

Security

Fixed The staff console has its own sign-in, and a second factor is required. Being signed in to the account app no longer opens the console. Staff ask for a sign-in link on the console (10 minutes, one use, and the same answer whether or not the address is staff), then confirm with a staff passkey, an authenticator app code or a recovery code; a staff passkey alone also signs in. Anyone without a factor, break-glass superadmins included, must add one before anything else and gets 10 recovery codes, shown once. The console session is its own cookie (`__Host-`, HttpOnly, SameSite=Strict), ends after 12 hours or 30 idle minutes, and gets a new id at every second factor. Wrong codes lock after five tries, for longer each time. Every state-changing console request must come from the console's origin. Adding or removing a factor needs a second factor from the last 10 minutes; deletions and impersonation from the last 30. Removing someone's staff access or changing their role ends their console sessions. Sign-ins, factor changes and used recovery codes are in the audit log, and factor changes and used recovery codes ring the bell for the person and for superadmins. The Profile page has a Security card for passkeys, the authenticator, recovery codes and console sessions. Set `XSPEED_HUB_ADMIN_URL` before deploying; a lost factor is reset on the box with `dist/ops/admin-auth-cli.js`. See [admin-auth](docs/architecture/admin-auth.md).
Fixed A mail that cannot be sent no longer puts its body in a production log. The fallback logs the recipient and subject; `XSPEED_HUB_LOG_MAIL_BODY=1` restores the old behavior on a box that has to read a sign-in link from the log.
Fixed Requests to customer sites check the address they connect to. The Hub checked a site's address and then looked it up again to connect, so a site whose DNS changed in between, or one that redirected to a private address, could make the Hub call into its own network. Every connection to a site's MCP endpoint, its attach callback and Slack webhooks is now checked at connect time, redirects included. 6to4, Teredo, documentation and zone-scoped IPv6 addresses are refused as well.

Added

New Add a minimal website account menu API using the existing Hub browser session, with exact-origin checks, session-bound CSRF, guarded workspace switching and fixed website login returns. It is on by default only on the production Hub (`NODE_ENV=production` with the canonical `https://app.xspeedcache.com`); `XSPEED_HUB_WEBSITE_SESSION=0` turns it off and `1` turns it on elsewhere. Refresh Hub identity before showing account views after a tab is restored or focused; clear all configured customer cookie scopes on logout.
New Add a signup-first guide for the free WordPress plugin, with expiring domain-only pending setup per person and workspace, existing plugin/token pairing, and a return to the website experience. Saving a domain never grants site access or imports a scan.
New Site icons come from the Hub. The app used to load each site's icon straight from the site, in the viewer's browser, on every paint, and it often failed. The Hub now fetches the icon itself (the Site Icon the plugin reports, then the home page's `<link rel="icon">` tags, then `/favicon.ico`), stores it, and serves it at `GET /sites/:id/icon`, so the browser makes no third-party request. Capture runs in the background on attach, Re-verify and the daily site pass, refreshes weekly and backs off after a failure. Every hop is checked by the SSRF guard, redirects are followed by hand, reads are capped at 200 KB, and only PNG, ICO, JPEG, GIF and WebP bytes are kept, typed by their magic number; SVG is refused. A site with no icon yet still shows its first letter. The staff console shows the same icons in its Sites list and on the site page.
New A notification bell for the staff console. Staff learn about a support request, a site that stopped answering, failing speed tests, a struggling renderer, a render storm, a stuck Cloudflare Enterprise registration, a staff role granted or removed, an impersonation, or a new Pro workspace without watching the dashboard. Events ring it when they happen; conditions are checked every five minutes and reported once while they hold, so a week-long outage is one line, and many sites failing together are one line too. Each row only reaches staff whose role can open where it links, the person who caused it is not told, and rows go after 30 days. Clicking a row marks it read and opens the page or filtered list behind it. `GET /admin/notifications`, `POST /admin/notifications/:id/read` and `POST /admin/notifications/read-all`.
New A Cloudflare Enterprise license now stays with its domain. The Pro license is a seat and is meant to move between sites; a CFE purchase is a domain on a shared enterprise account with a per-domain cost upstream, so releasing one name and registering another mid-term spent two domains against one purchase — and every registration looked correct on its own while it happened. Enable refuses with `409 licence_bound`, naming the domain that holds the license, what state it is in and when it comes free, because a refusal that will not say where the license is held is a support ticket rather than a control. The apex and its `www` form are one name, and asking for the domain already held is not a refusal — it resolves to the existing registration, so host migrations and URL changes still work. The binding runs after the control proof and before displacement, and lasts as long as the subscription is continuously paid; per-term binding, which would open a window at each renewal, needs a schema change and a product decision and is specified but not built.
New Cloudflare Enterprise for a site's own domain. A site running xSpeed Pro can put its domain on Cloudflare Enterprise through the Hub: pre-flight checks (does the name resolve, is it already behind someone else's Cloudflare, does the origin serve HTTPS), the DNS records to add, pause and resume, edge settings, and a whole-domain cache purge. The Hub holds the xCloud enterprise credential so the plugin never has to — a site authenticates with its own site token and nothing more. The site page grows a Cloudflare Enterprise tab showing the status, the outstanding DNS records, and the records that were live before the cutover, which is what a user needs if they ever take the domain back off. The "Open in xCloud" SSO link is off unless an operator sets `XCLOUD_CFE_SSO=1` — it signs the visitor in as the shared enterprise user, so it belongs only on a deployment with one xCloud user per customer.
New Cloudflare Enterprise follows the site's own cache headers. The Hub now sets `edge_ttl_mode: respect_origin` on every domain it registers, and a pass on the poller catches up domains registered before. Cloudflare then keeps a page as long as the plugin's `CDN-Cache-Control` says and skips any page marked `no-store`. Under xCloud's default it stored every page for four hours whatever the site sent, including an unoptimised first render. `XCLOUD_CFE_RESPECT_ORIGIN=0` stops the Hub setting it.
New Staff can see the Cloudflare rules acting on a registration. A Rules button on both Cloudflare Enterprise views reads xCloud's rules lookup and shows each rule's id, action and limits. It also flags a protection the settings show as on when no rule applies it, which was true of the WAF and rate limiting on two test domains.
New Each registration carries the Hub's own reference at xCloud. New registrations are created with `external_ref` (`xspeed-hub:<Hub host>:<row id>`), older ones get it from the poller, and recovering a registration whose create timed out now looks it up by that reference before searching by name.
New One verdict per routing name for Cloudflare Enterprise. The domain status now carries `routes`: for each name a visitor types, whether visitors reach the edge, the origin, or nothing yet, which option (CNAME or A records) is in place, and any old record that must be removed. Before this, a CNAME row could read "live" while an old A record beside it sent every visitor to the origin. The per-record states are unchanged.
New Two more staff diagnostics. "Addresses the SSRF guard refuses" lists site and webhook hosts that resolve to a private address or not at all, and "Background loops" flags a loop that failed, never started or stopped running on schedule.
New Diagnostics in the staff console. System has a Diagnostics tab with three fixed, read-only diagnostics: unreachable sites grouped by cause, sites rendering an unbounded URL space, and stored secrets that do not decrypt with the current key. Each shows who ran it last. A run reads the database only, stops at its deadline, and is audited with counts alone.
New Timeline and staff notes in the staff console. A user page and a workspace panel show what happened, newest first: sign-ins, workspaces and members joined, sites attached, AI activity and speed tests per day, and what staff did. Staff can leave notes on a user, a workspace or a site that every staff member sees and the customer never does. The audit log records that a note was added or deleted, not its text.
New Bulk actions in the staff console. Sites and Tokens have a checkbox on each row. Staff can test or re-verify up to 25 sites at once, with the failures listed by site, or revoke up to 100 AI tokens at once behind a confirmation. Each site or token gets its own audit row, as before.
New Connect a site by its address. Add site now asks for the site's address and sends you to its wp-admin to approve; you come back with the site connected, without copying a token. Local and private addresses get a message instead, and the token form is still there under "Use a token instead". Needs xSpeed Cache with Hub connect on the site.

Changed

Improved The staff console's account menu is an avatar at the end of the top bar. It sat at the foot of the rail with the full email and role; the menu now shows those when opened. The avatar is the person's Gravatar, with initials when there is none, as in the app, and a Profile item opens a Profile page with the picture, the role, the theme and a "Reduce motion" switch for the console. The theme button left the top bar, and the bell and the avatar sit together at its end, on one line with the rest of the bar. Search (⌘K) finds pages from the first letter as well as users, workspaces and sites, and lists every page before anything is typed. A loading table draws its skeleton as the account app does, and a table that fills the page fills it with skeleton rows instead of five rows over an empty half.
Improved The staff console looks like the account app. Every table stays inside the window and scrolls under a header that stays put, with the same fades at the top and foot; list pages such as Sites and Workspaces used to grow past the window instead. Checkboxes and radio buttons are drawn in the app's style rather than the browser's grey box. Dialogs have more room, a larger title and a shaded footer. The rail shows the bare mark with "Admin" beside the name, as the app's rail does. On the dashboard, the health panel no longer leaves its lower half empty, and "Needs attention" lists every check, passing ones with a tick, so it fills the height of the staff activity list beside it. While the console checks who is signed in, it shows the pulsing xSpeed mark, as the app and the plugin do, instead of a spinner and "Loading…".
Improved Cloudflare Enterprise no longer needs a Hub connection. A site with the add-on licence can check its status, put its domain on the edge, purge and manage it without ever connecting to the Hub, or after disconnecting. The licence decides entitlement; the workspace plan is consulted only for a request that carries no licence. A connected site keeps working as before, and a registration made before licences existed is still reached through its connection.
Improved Disconnecting a Cloudflare Enterprise domain no longer cancels it. It disables the registration upstream instead, so the domain keeps its place on the subscription and one Reconnect brings it back; cancelling threw away something the customer was still paying for and made returning a fresh purchase. A real release is still there behind `{mode: 'release'}`, and is still what happens automatically to a registration that never went live, one that failed, and one whose subscription has ended past its grace window — upstream allows a hostname exactly one registration platform-wide, so a row nobody will reclaim has to be reapable. What has not changed is the customer's DNS: disabling deletes the custom hostname at Cloudflare, so the site is unreachable until their records point back at their origin, and the panel says so on both paths.
Improved Reconnecting re-reads the DNS instructions before answering. Upstream mints a fresh custom hostname on enable, which changes the ownership TXT and the DCV target while leaving the routing records alone. The panel had been showing whichever validation records were stored from last time, so a customer following it would add records that could never validate — and, if they then moved routing back to the edge, would be serving a hostname that had verified nothing. Observations from the previous registration are cleared at the same time, so a rail cannot show the old cutover's passing checks over a new one.
Improved Retries read xCloud's error codes. Whether a refused Cloudflare Enterprise call is worth retrying, whether an enable was refused because the domain is already on, and whether a failed registration can be recovered are now decided from `errors.code`, not from the English message. A message is read only when a refusal has no code. When xCloud saved a settings or origin change but could not push it to Cloudflare, the Hub now shows what was saved.
Improved The app says Cloudflare where it said edge. The Cloudflare Enterprise tab's settings heading, cache rows, source pills, page-caching switch, resume button and remove card now use the same labels as the WordPress plugin.
Improved A licensed status read re-links a registration to its site. When the plugin reads its Cloudflare Enterprise status with the licence that owns the domain, from a site verified now at the domain's address, and the registration names no site or one that has disconnected or stopped verifying, the Hub points it at the reading site. Disconnect and site removal then find it. The dashboard also stops offering actions on a domain managed from the plugin.
Improved The "already uses Cloudflare" pre-flight check now says how to fix it. It tells the customer to set the record to DNS only (the gray cloud) in that Cloudflare account and run the checks again, and to ask their hosting company if it manages that account.
Improved AI connections that sit unused for 30 days must sign in again. A refresh token now lives 30 days from when it was issued, as intended all along; each refresh starts a new 30 days, so a connection in use never notices. Before, a leaked refresh token worked forever. Connections made with a pasted connection token are unaffected.
Improved Database connections stay open between requests. The pool used to close a connection after 10 seconds idle, so the first request after a quiet spell paid to open a new one: four or five round trips to the database, close to a second when it is far away. Connections now stay open and are replaced once an hour, with TCP keepalive so a firewall does not drop them silently.
Improved The staff console looks like the account app. It has the same rail, which now collapses, and the same top bar, which carries each page's title, subtitle and main buttons. Text sizes, buttons, cards and tabs match the app. Charts show a card with the date and value on hover. Detail rows open in a panel beside the table, so the list stays in view. Lists start with summary cards drawn from live numbers.
Improved The render box fills up to what it can really take. It used to read the 1-minute load average, charge every render started in the last minute a whole core, assume 1200 MB per render, and raise its offer by one per reading, so jobs queued while the box sat mostly idle.
Improved It now reads CPU busy share and Linux pressure over seconds, and measures what a render costs from its own browser processes.
Improved It keeps a minimum running (4 by default) even when the CPU is busy, using at most half the memory it keeps free, and stops at rock bottom.
Improved The Hub asks the box for room every 3 s while work waits, instead of waiting for a render to answer, and sends its saved settings with each ask.
Improved Every limit is a setting under Renderer settings, and the admin page shows which one is holding the box.
Improved One site gets the same Overview as many. A workspace with a single site now shows the score with its trend chart and the site list, the same layout a workspace with more sites gets, instead of a separate single-site card.

Fixed

Fixed A fresh load no longer shows the boot logo twice. It went logo, skeleton, logo, content: the focus a browser fires right after loading, and a late `pageshow`, each re-checked the session and hid the page. Focus now re-checks only after the window was left, and `pageshow` only on a back/forward cache restore. Returning from another tab still re-checks.
Fixed A Cloudflare Enterprise domain waiting on DNS no longer fails every status poll. `domain_not_live` joined the allowed statuses in the table definition on 2026-09-02, but a table created before that kept its old check, so each poll that saw xCloud report the status was refused and the row stayed `pending_verification`. Boot now widens the old check.
Fixed Keep Overview scores, cache statistics and recommendations intact when focus rechecks the same session; hold requests during identity verification and continue rejecting responses from a different user or workspace.
Fixed Deleting a workspace no longer strands a live registration at Cloudflare. The cascade removed every registration under the workspace locally and cancelled none of them, leaving a hostname served forever that nobody could register again. The delete now names the domains, takes them off the edge only after an explicit acknowledgement, and warns that DNS has to be pointed back first. Leaving a workspace as its last member, or deleting your account, is refused while any of them is live.
Fixed A Cloudflare rate-limit challenge is no longer reported as a failure. Sites on xCloud's Cloudflare zone share one rate limit per Hub address. When it challenged the Hub, the MCP check said the site's token was rejected, the daily re-check marked the site unreachable, and the daily licence re-check counted a failure against the customer. Each now reports the challenge, leaves the site's state alone and tries again later. The Hub's daily loops are also spaced to at most 100 calls a minute and pause for 10 minutes after a challenge.
Fixed Old sign-in and connection records are cleared. Expired sessions, sign-in links, authorization codes and dead AI connections are deleted hourly, and registered AI clients that were never used are removed after a week. Registering clients is limited to 20 an hour per address.
Fixed One bad site token no longer stops the daily check for every site. A stored token that cannot be decrypted (written under another key) used to end the daily re-verify before it checked anything, every day, with nothing logged. That site is now marked unreachable with the reason, the rest of the fleet is checked, and nothing is sent to the site with an empty token. Each background loop's last run and last error show under System → Health.

v1.4.1

2026-09-29

A smoke test runs after each release. When a push to `main` creates a new version, and after each dev deploy, a test account signs in, connects a test site, reads it, turns a setting on and off, approves an assistant and makes an MCP call, then removes the site and connects it again. The result goes to the run summary, and as a comment on the pull request merged into `main`, or, when there is none, on the most recent merged pull request that contains the commit. `npm run release:check` is the one local gate to run on `dev` before a release.

Added

New A smoke test runs after each release. When a push to `main` creates a new version, and after each dev deploy, a test account signs in, connects a test site, reads it, turns a setting on and off, approves an assistant and makes an MCP call, then removes the site and connects it again. The result goes to the run summary, and as a comment on the pull request merged into `main`, or, when there is none, on the most recent merged pull request that contains the commit. `npm run release:check` is the one local gate to run on `dev` before a release.
New Passkeys and two-factor for your account. Sign in with a passkey, or add a code from an authenticator app after your password, email link or Google, with ten single-use recovery codes. Both live under Profile → Sign-in security.
New See where you're signed in. Each session shows its browser, system and network, and you can end one on its own. A browser that has never signed in to your account before sends you an email.
New Confirm it's you before risky changes. Connecting or rotating the AI connection, changing sign-in security and deleting things ask for your passkey, or your password and a code, when you signed in more than 15 minutes ago.
New The security checklist runs as a test suite. `npm run test:security` boots the real Hub against a scratch database and fake sites and runs checks 1 to 10 of the security audit, except the prompt-injection check, which stays manual. The role checks are generated from the route tables, so a new route is covered when it is classified. It runs in CI and in `npm run release:check`, and the release pull request gets its report as a comment.

Fixed

Fixed Critical CSS survives a first render of a large page. The Hub gave up on the site after 20 seconds and reported "Site unreachable" while the site was still rendering. `generate_critical_css` now waits up to 50 seconds, says to try again in a minute when a first render is still running, and takes an optional page `url` so it can build Critical CSS for a page other than the home page.
Fixed Critical CSS leaves out hover, press and focus rules. Nothing is in those states at first paint, and the rest of the stylesheet arrives before anyone can hover. On essential-blocks.com the fold set went from 966 to about 750 selectors.
Fixed The speed scan stops suggesting features that are already on. A fix for lazy loading, JS or CSS minification or WebP/AVIF now says the check fails for another reason when the site already has that feature on, instead of asking you to turn it on again.
Fixed Pages wait for their data instead of flashing an empty state. The Overview showed "No sites yet" and "Your fleet looks healthy" on every load, and Sites, Activity, Members, Plan, notifications and the Performance page showed their empty message, before the real content arrived. Each now shows a loading placeholder until its data is in, and a failed load shows its error instead of an empty state. The AI connection card no longer opens full size and then folds, so the page stops jumping.
Fixed The fleet score bar fills its card.

Security

Fixed Every AI write checks your role on that site. Six tools (object cache on/off and flush, Cloudflare purge and development mode, speed test, speed scan) skipped the per-site check, so a Viewer, or a connection that holds a site read-only, could still run them. They are now refused like every other write.
Fixed The address check refuses IPv6 forms of private addresses. A site URL such as `https://[::ffff:127.0.0.1]` could pass the guard that keeps the Hub from calling internal addresses.
Fixed Secrets in AI tool arguments stay out of the activity log. API tokens and licence keys passed to a tool were stored as typed; they are now redacted, the same way the staff audit log already did.

v1.4.0

2026-09-28

A site whose token changed reconnects by itself. Rotate, Disconnect then Connect, or a reinstall gave the site a new token the Hub never learned, so every check failed until the site was attached again. The site now sends its new token to the Hub, which checks it before keeping it. A live `.dev` site is no longer taken for a local one, and the daily check tries a failed site once more before calling it unreachable.

Fixed

Fixed A site whose token changed reconnects by itself. Rotate, Disconnect then Connect, or a reinstall gave the site a new token the Hub never learned, so every check failed until the site was attached again. The site now sends its new token to the Hub, which checks it before keeping it. A live `.dev` site is no longer taken for a local one, and the daily check tries a failed site once more before calling it unreachable.
Fixed Switches sit evenly in their track. The knob had 2px on one side and 4px on the other when on; it now has 2px all round in both states.
Fixed The Page cache card fits the module page's side column. Its four figures sat in one row there and broke "109 KB" over two lines; they now sit two by two, and the header wraps.
Fixed Site search results open above the page. again, not behind a site's sticky header.
Fixed Icon-only buttons match the buttons beside them. The ⋯ menu in a site's header was shorter than Run speed test and Purge cache; every button now has a fixed height, and an icon-only one is a square.
Fixed An empty Top fixes list uses the Hub's empty look. , a green tick and one line, centred in its card.
Fixed "Sites, worst first" puts a site with a known problem on top. even before it has a speed test. A site with a cold cache and no desktop run ranked below a healthy one scoring 92.
Fixed Collapsing the sidebar no longer moves its icons. Every icon, the logo and your avatar stay where they were; only the words go. Hovering an icon in the collapsed sidebar shows its name.
Fixed A module's settings no longer vanish. after "Show settings" or after turning the module on or off. The page went blank until a full reload.
Fixed Search fields show one clear button. , not the browser's and the Hub's side by side.
Fixed Row menus are no longer cut off. The Sites table's ⋯ menu showed an item and a half; menus now open above the page and flip upwards when there is no room below.
Fixed Focus is a thin outline, not a black box. Clicking a control no longer draws the browser's heavy ring; keyboard focus shows a primary-colour outline, and text fields show focus with their border.
Fixed Apply fix now shows the fix as done. Recommendations are read from the site's last daily snapshot, so after a fix landed on the site the same card came back until the next day, and Apply looked like it did nothing. Applying a fix now takes a fresh snapshot of that site first.

Changed

Improved A clearer site header. The site's own icon leads: the Site Icon the plugin reports, else its favicon, else its first letter. The name and its status share the first line, and the address and xSpeed Cache version sit under them as plain text, with a Pro badge when Pro runs. It is compact on every page but the site's Overview, and the sidebar's site tile shows the same icon.
Improved Loading shows the xSpeed mark. , pulsing in the middle of an empty page as the plugin's dashboard does, from the first paint and in the saved theme. The sign-in header no longer flashes in first.
Improved Site details and Access use the whole width. Site details keeps its facts on the left and renaming and detaching on the right, with an outlined Detach button; Access explains beside the list that adding one person restricts the site to the people listed.
Improved Saving a setting takes one trip to the site instead of two. , and moving between a site's pages no longer waits on the site each time. The Hub keeps what the site reported for 30 seconds and forgets it on any change made through the Hub. A switch is usable again as soon as the site accepts the change, and the page takes the saved values from the site's answer instead of loading the whole site again.
Improved The Overview ranks at most five sites. The rest are behind "View all N sites", which opens the Sites list.
Improved Long tables stay inside the window. Activity, Sites, Plan, a scan's history and a site's speed-test runs scroll inside the table once they are longer than the screen, with the header row kept in view. The table shows no scrollbar of its own; a fade at its foot says more rows follow.
Improved Headers stay in view and content fades under them. Every site page keeps its header (and a module's pills, or a report's section nav) at the top while it scrolls. Content passing under it, under the Hub's top bar, under a table's header row or under a report dialog's title fades out instead of being cut off. On a phone the site Overview's full header card still scrolls away.
Improved Group pages show modules as a grid of cards. , like the plugin's own group page: an icon, the switch, a two-line summary and the settings count. Modules managed only in wp-admin are quieter cards at the end, in place of the folded list. Icons beside All / On / Off switch to a list, and the Hub remembers the choice in that browser.
Improved The plugins go by their full names. xSpeed Cache and xSpeed Cache Pro, in place of "xSpeed", "xSpeed Pro" and "the Free plugin".
Improved Module pages have the module pills back. A row of pills above the module name lists the other modules in its group, so you can move from one to the next without going back up. On a site without Pro, a Pro module's pill has a lock and opens the upgrade details.
Improved A Free site shows what xSpeed Cache Pro adds. Its settings list the Pro modules it lacks, locked and marked Pro, and turning one on opens a short upsell with a link to xSpeed Cache Pro. On a site that runs Pro, Pro modules carry no badge.
Improved Plan is about the plugin on each site. The Hub is free, so Plan no longer describes it as a plan. It lists each site's xSpeed Cache version and whether it runs Pro, links to the site's Plugin & license page, and offers xSpeed Cache Pro for the Free ones. "Included in xSpeed Cache Pro" on a site's audit links there too. Every role can open it.
Improved Empty sections say what the emptiness means. "No sites yet" and "No speed tests yet" offer the one action that fills them, "Everything looks healthy" shows a green tick, and a search or filter that matches nothing says so with a Clear filters button instead of looking like missing data.
Improved Checkboxes match the rest of the Hub. : a rounded box with a primary fill and a white tick, a dash when partly checked, the same everywhere.
Improved Access is easier to read. : one row per choice, a switch for read-only, and the tools split into Read and Change with a count for each.
Improved The AI connection stays in one place on Home. It is the first card before and after connecting: open while you set up, one line after you press Done (working, waiting for the first request with a prompt to try, or failing), and Manage opens the setup right there. It used to jump from the top of the page to the bottom the moment you connected.
Improved A fix applied from Home stays on the list as a green "Done" row. , so it is clear it worked.
Improved Automation uses the whole page. Each setting is one row with its control on the right, like a module page, and Autopilot's recent changes sit in a column beside the settings instead of under them.
Improved Members shows people, not a table of emails. : avatar, name, email, who invited them and when they joined. Pending invitations say when they expire.
Improved The danger zone is calmer. : a plain card with the risk in words and an outlined delete button, instead of red on red.
Improved Settings read in the plugin's order and hide what does not apply. A module's settings keep the order the plugin lists them in instead of alphabetical. Settings that only matter for another choice (Memcached host while the backend is Redis) hide until that choice is made, the same rule wp-admin uses, and settings most sites never touch fold under "Advanced". Needs xSpeed Cache with the schema hints; older sites show every setting as before.
Improved New modules land in the right group. because the plugin now says where each module belongs. Turbo Render and Privacy no longer sit under "Other".
Improved Module pages are quieter. The "More in" list is gone (the sidebar already lists the group), and the side column is one card. Settings labels are in sentence case, and every control lines up in the right-hand column.
Improved Boost opportunities are one line each. , with the explanation under Details and at most one button. WP-CLI commands no longer appear.
Improved Automation saves like a module page. : switches for what turns on, and one "N unsaved changes · Discard · Save" bar per card.
Improved Buttons, cards, inputs and loading states match across the app.
Improved Easier to read. Hints and descriptions are darker (the same grey the plugin moved to, which passes WCAG AA) and nothing is smaller than 12px except pills. Inside a site the page title is the largest heading, not the site name.
Improved Health leads with what needs a look. Failing and warning checks come first, passed checks fold into one line, and the checks fill the page instead of a side column.
Improved Activity reads in words. : "Purged cache · Page cache · Dashboard" instead of `purge_cache`, `type=page` and `dashboard`.
Improved Less repetition. Automation and Connect AI lose side cards that said what the page already said, and Automation's fields have visible labels.
Improved Phones. the breadcrumb shows only where you are and one step up, and Purge all no longer uses a bin icon.
Improved A site has its own sidebar. Opening a site swaps the menu for that site's pages: Overview, Performance, then its settings in the plugin's own groups (Cache, Optimization, Network, Health & insights, Tools, AI & agents), then Plugin & license, Access and Site details. The four tabs are gone, and a switcher at the top jumps to the same page on another site.
Improved Every module has its own page. , with its on/off switch, its settings and, where it has one, its live status beside them: the Preloader's progress, the Health checks, the page cache figures. A group page lists its modules with what each does and a switch, instead of collapsed rows.
Improved Settings save when you press "Save to site". Nothing is sent to a live site on its own any more; edits wait in a bar at the bottom of the page. A value typed back to the site's own stops counting as a change, and a bad value blocks the save and says why. A module that is off folds its settings away until you ask for them.
Improved Clearer fields. A unit in a setting's name (seconds, minutes, ms, %) moves beside the box, long durations read back in words (*= 1 year*), short choices are buttons, and lists count their entries. A setting the Hub can't change still shows its value, with a link to wp-admin.
Improved The site header carries Purge cache and Run speed test. on every page of the site. Purge has a menu for clearing one kind of cache: page, CSS and JS files, object or REST.
Improved Search inside a site. from the top bar (⌘K, or /) finds any module or setting and opens it with the setting highlighted.
Improved Wide screens are used. Home and a site's pages grow to 1440px; Home puts the fleet next to Boost opportunities instead of one long column.
Improved A site is Online, not "Verified", and Re-check replaces "Re-verify": the workspace has one AI connection, and the pill only says whether the site answered.
Improved Old `/sites/<site>/settings/…` and `/reports/…` links open the matching new page.
Improved Performance says what to do next. The page opens with the latest mobile and desktop scores, the change since the run before, a trend line and the Core Web Vitals coloured by PageSpeed's bands, plus Top fixes: each finding from the latest runs that an xSpeed Cache module fixes, linked to that module. A single report colours its readings, shows the change on each since the previous run, gives every fixable finding a button to its module, and lines up with the page instead of sitting in a centered box. The report table colours its metrics the same way.
Improved No empty right side. Every page uses the full width. Automation, Connect AI and Support put their forms in a main column with a narrower column of help beside it; Profile keeps its details in the main column and lists sign-ins beside them, capped at five with this device first.
Improved Every workspace page starts at the same left edge. with one heading. Pages no longer repeat their title under the top bar, their buttons sit in the top bar, and Purge all shows only on Overview and Sites.
Improved The Sites list is a table. : status, score, hit ratio, page cache, xSpeed Cache version with Free or Pro, open fixes and last check, with search, filters, worst-first sorting, a row menu, and bulk Purge and speed test.
Improved Automation. is a page of its own for monitoring alerts and Autopilot, which used to sit above the Activity log. Viewers see the settings read-only. Activity is now the log alone, in pages of 50, with filters for site, action and result.
Improved The menu is grouped into Workspace, Manage and Account. Members lists what each role may do; Support links to the xSpeed docs and support.
Improved Module pages. always have a side column (state, plan and a link to the module in wp-admin), and the module pills slide with arrows instead of showing a scrollbar.

v1.3.9

2026-09-25

Render capacity is measured, not configured. The render box now reports, on every answer, how many more renders it can take from its load average and free memory, and the Hub sends that many and queues the rest. The fixed three-at-a-time worker, the 120-an-hour and 500-a-day per-site caps, one render per site at a time, and the 2–10 s pause between a site's renders are gone; the caps and the pause stay as settings, off. Nothing is refused for lack of room. See [ADR 1](docs/adr/0001-render-capacity-is-measured.md).

Changed

Improved Render capacity is measured, not configured. The render box now reports, on every answer, how many more renders it can take from its load average and free memory, and the Hub sends that many and queues the rest. The fixed three-at-a-time worker, the 120-an-hour and 500-a-day per-site caps, one render per site at a time, and the 2–10 s pause between a site's renders are gone; the caps and the pause stay as settings, off. Nothing is refused for lack of room. See [ADR 1](docs/adr/0001-render-capacity-is-measured.md).
Improved Every render goes through one queue. `POST /site/ucss/measure` makes a high-priority job and holds the request on it for up to 90 s. A render still running then answers `504 render_pending`; it carries on, and the plugin's next ask gets the result, after a check that the page has not changed since. A caller that hangs up no longer cancels its render. One ask is one render: a failure is answered, not retried, and a firewall block page is never retried by the queue either. While the renderer cannot be reached the route answers `502 renderer_unavailable` at once. Jobs of the site with the fewest renders running go first after the waited-on ones, so one site's backlog cannot hold up everyone else's.
Improved A per-site circuit breaker replaces the 24-hour pause. One firewall block page no longer stops a site for a day. The breaker pauses a site when more than half of its last renders failed across at least three pages, holds its queued renders (nothing is failed), then sends one test render; a failed test makes the next pause five times longer, up to 6 h. Only failures known to be the site's count: page faults, block pages, and a server that cannot be reached. Renderer timeouts, our own renderer's crashes and failures of unknown cause never do. The queue no longer fails a site's other jobs on a block, and no longer refunds quota.
Improved Health grading no longer counts renders in flight. , so a busy but healthy box no longer drops the queue to one render at a time. Only an unreachable renderer pauses the worker.
Improved The renderer relaunches its browser when it crashes, instead of failing every render until the process restarts, and exits on SIGINT/SIGTERM instead of lingering without a browser. It removes the profile folders of browsers that died with their process, which nothing removed before.
Improved Skipping third-party widgets, off until switched on. With `render.third_party_blocking` on (System → Renderer settings), renders skip YouTube, Vimeo and Google Maps iframes, and a chat or push widget (Intercom, Drift, Tawk, Crisp, Zendesk, LiveChat, Tidio, OneSignal) on any site where two renders found no site CSS styling it. Each render checks this and the Hub keeps the verdict per site; one styled selector keeps the widget loading there for good. Off, the checks and byte counts still run, and Renderer charts shows what skipping would save. `scripts/render-compare.mjs` renders pages both ways and diffs the measurement. On a test page a YouTube embed cost 5 MB a render and changed nothing measured.
Improved Unchanged pages are answered from their last render. The Hub keeps each page's last result with a fingerprint of its HTML and stylesheets. Asked for the page again within an hour of that render, the renderer loads only the HTML and CSS; if neither changed, the saved result is the answer (logged `reused`) and the site serves its HTML and CSS instead of the whole page: no scripts, images, fonts or third parties. An edit to the page or a stylesheet renders in full at once. This is what bounds the rebuild loop in released Pro now that the daily cap is off. `render.reuse_max_age_minutes` (60) sets the hour; 0 turns it off.
Improved Logs rotate themselves. The renderer's processes and the Hub each keep their PM2 log files under a size (20 MB and 50 MB) with two older copies, so neither box's disk fills with logs and no PM2 module has to be installed.

Added

New System → Renderer settings. in the staff console: the render box's load target, memory per render and ceiling, an incident pin, the queue's bounds, every breaker threshold, and per-site pacing. Saved in `platform_settings`, audited as `renderer.settings.set`, applied within 15 s. The render box polls `GET /renderer/settings` for its own three.
New The Renderer tab shows renders out against what the box allows, its load and free memory; the charts tab shows the last 24 h of both, and the breaker's pauses. "Daily cap use" is now "Busiest sites, 24 h" and counts only renders that ran.
New Render-log rows record how long each render queued, how many were out when it left and how many were allowed, for tuning later. The render box is sampled every 30 s. Retention: samples 14 days, the render log 30 (it had no limit before).
New `scripts/render-load-test.mjs`: fire N renders at concurrency C at the renderer or through the Hub and report the status mix, timings and credit.
New Render stats. on System → Renderer charts, by hour, day, month or year: renders, failures (the site's vs. ours), queue wait, peak concurrency, bytes downloaded, and time the box spent full with work waiting. Daily totals are kept for good (`render_daily`), per-site totals 400 days. Each render now reports what it downloaded by kind, and the page shows what the image/font cache saved and what capping video or replacing images would save, so those changes can be judged on numbers before anyone makes them. The Renderer tab shows the render box's free temp disk, which also feeds health: under 10% free warns, under 5% or 1 GB is critical.

Fixed

Fixed The unchanged check reads no more than 8 MB per file. It fetched the page's stylesheets whole: two 255 KB gzip stylesheets decoded to hundreds of MB each and took the renderer past a gigabyte, with every render in the process at risk. The document and each stylesheet are now streamed and dropped past 8 MB decoded; a page past the cap gets no fingerprint and simply renders in full each time.
Fixed Fingerprinting a hostile page no longer stalls every render. The HTML normalisation's patterns rescanned the document from every unclosed tag or long unbroken script string — seconds of event-loop time a site could cost everyone. The scans are now linear; the output is unchanged.
Fixed A slow page whose HTML differs on every request gets its result. The sync route keeps a finished result while re-checking it against the page, and answers with it when the check outlasts the wait or the queue is full — instead of a 504 on every ask, forever.
Fixed The render box losing its own network no longer trips every site's breaker. A connect or read timeout and an unreachable address are no longer counted as the site being down, since a local outage produces exactly those for every site at once and the escalating pauses would outlast it by hours.
Fixed A stalled renderer `/stats` no longer holds the queue. The health probe's deadline now covers reading the body; one that sent headers and then hung held the job worker's claims for five minutes.

v1.3.8

2026-09-23

Sites that block anonymous REST can now attach and be controlled. Verify and the tool proxy reached sites only over `/wp-json/xspeed/v1/mcp`, which a security plugin's "restrict REST API" setting 401s for every anonymous request — so a valid token was reported as "rejected" and such sites could never attach. Verify now probes the plugin's own `/xspeed/mcp` endpoint first (REST stays the plain-permalink fallback), a REST-gate 401 is reported honestly with the setting to change, and proxied tool calls retry over JSON-RPC on the pretty endpoint. (#214)

Fixed

Fixed Sites that block anonymous REST can now attach and be controlled. Verify and the tool proxy reached sites only over `/wp-json/xspeed/v1/mcp`, which a security plugin's "restrict REST API" setting 401s for every anonymous request — so a valid token was reported as "rejected" and such sites could never attach. Verify now probes the plugin's own `/xspeed/mcp` endpoint first (REST stays the plain-permalink fallback), a REST-gate 401 is reported honestly with the setting to change, and proxied tool calls retry over JSON-RPC on the pretty endpoint. (#214)

v1.3.7

2026-09-23

Render history survives deploys. Every render the Hub asks for is now recorded in Postgres (`ucss_render_log`), and the admin console's Renderer tab reads from it: a deploy no longer wipes the recent-renders table, and a new "Load older renders" control pages back through the whole history, however old. A Hub without a database keeps the previous in-memory behaviour. (#205)

Added

New Render history survives deploys. Every render the Hub asks for is now recorded in Postgres (`ucss_render_log`), and the admin console's Renderer tab reads from it: a deploy no longer wipes the recent-renders table, and a new "Load older renders" control pages back through the whole history, however old. A Hub without a database keeps the previous in-memory behaviour. (#205)
New Asynchronous UCSS renders. A plugin can submit a page with `POST /site/ucss/jobs` and collect the result later with `GET /site/ucss/jobs/:id`, rather than wait up to 45 s on the measure route. It can also ask for a ping when the job is done. The queue is in Postgres (`ucss_jobs`), so it survives restarts and deploys. A job whose process died goes back in the queue when its lease runs out, and on SIGTERM running renders finish or return to the queue without spending an attempt. The worker stops taking jobs while the renderer is down. Jobs keep the measure route's limits: the same checks and caps, and one render per site at a time. The System → Renderer tab shows the queue. The measure route is unchanged for released plugins.
New Filter, sort and chart the renderer's work. The System → Renderer tab's recent renders filter by URL, outcome and site and sort by time, site or duration, and keep the last 1,000 renders instead of 200. A new Renderer charts tab beside it shows outcome counts, renders and errors per hour over 48 h, how long renders take, sites paused by a firewall block, the busiest sites and each site's use of its daily cap.

Fixed

Fixed Render guards survive restarts. The hourly and daily render caps, the page lock after two failures and the 24 h pause after a firewall block now live in Postgres (`ucss_site_state`, `ucss_page_state`), not process memory. Before, a deploy the morning after a BlogVault block re-opened that site to the renderer at once. If the database doesn't answer, the measure route falls back to the in-memory guards rather than refusing. The caps are now keyed by the site's origin, like the block pause.
Fixed The UCSS renderer behaves as a guest on customers' sites. It no longer counts as a visitor in their analytics: GA4, Cloudflare RUM, Meta Pixel, Clarity, Plausible, Fathom, Matomo, Jetpack Stats and the WordPress analytics plugins' collection requests are refused, while tag managers, consent banners and other scripts that add visible UI keep loading, so the measurement is unchanged. A security plugin's block page (BlogVault, MalCare, Wordfence, Solid, Shield, Defender, NinjaFirewall, CleanTalk) now pauses every render for that site for a day (`423 renderer_blocked`) instead of each page retrying into a worse block. One render runs per site at a time, a missing asset is fetched once per render instead of once per viewport, and a render is cancelled when the plugin stops waiting for it. Refusals carry a `code` so the plugin can tell a page problem from a site-wide one.
Fixed The renderer stops re-downloading a site's images and fonts on every page. Each render started from an empty browser, so a site's logo, hero and webfonts were fetched from the customer's server again for every page measured. Images and fonts are now kept for an hour across renders (up to 64 MB per renderer process, `lru-cache`), and stylesheets and scripts are still fetched fresh so the measurement always sees the current CSS.
Fixed Renders of one site are spaced out, and a renderer process can't be flooded. The next render of a site waits as long as the previous one took, kept between 2 and 10 seconds (`XSPEED_HUB_RENDER_SITE_GAP_MIN_SECONDS`, `XSPEED_HUB_RENDER_SITE_GAP_MAX_SECONDS`), so a light page is followed quickly and a heavy one gets a longer pause. Each renderer process runs at most `RENDERER_CONCURRENCY` renders at once (default 2). Up to `RENDERER_QUEUE` more (default 16) wait for a slot, and the rest are answered 503 busy and retried later by the plugin.

v1.3.6

2026-09-22

Renderer monitoring in the admin console. — a new System → Renderer tab shows the UCSS renderer's graded health, render counters (failure rate, in-flight depth, p50/p90/max durations) and its access-log traffic history, via `GET /admin/renderer`; the system-alert poll now also watches the renderer and posts edge-triggered up/down lines to the operator channel. The tab also lists the recent renders — which URLs were measured, with outcome and duration — so staff can verify the right pages are being rendered, not just that rendering works.

Added

New Renderer monitoring in the admin console. — a new System → Renderer tab shows the UCSS renderer's graded health, render counters (failure rate, in-flight depth, p50/p90/max durations) and its access-log traffic history, via `GET /admin/renderer`; the system-alert poll now also watches the renderer and posts edge-triggered up/down lines to the operator channel. The tab also lists the recent renders — which URLs were measured, with outcome and duration — so staff can verify the right pages are being rendered, not just that rendering works.

Fixed

Fixed The UCSS renderer no longer runs all day against one site. A BlogVault-protected site answered the renderer with a login page reached through `?redirect_to=`, and the renderer kept rendering it, with every image and font, for more than nine hours. `POST /site/ucss/measure` now refuses URLs that carry `redirect_to`. It allows each page one retry before refusing it for 24 hours, and caps each site at 500 renders a day on top of the hourly 120. The renderer fails a page that redirects to a different path or answers 4xx/5xx instead of measuring the wrong page. Only failures the renderer blames on the page count toward the retry, so a renderer outage locks nothing. A home page that language-redirects (`/` → `/en/`) is now refused rather than measured as the other language, and those sites fall back to local pruning for it.

v1.3.5

2026-09-21

"Last seen" now reflects real activity, not just the nightly check. — every successful proxied call to a site (an MCP tool, a dashboard action, a report sync) touches the site's `last_seen_at`, debounced to at most one write per site per five minutes, and refreshes `plugin_version` when the site reports one. Previously both were only written by the daily re-verify, so an actively used site could show "Last seen 20h ago" and a freshly upgraded plugin kept its old version on the Overview card for up to a day.

Changed

Improved "Last seen" now reflects real activity, not just the nightly check. — every successful proxied call to a site (an MCP tool, a dashboard action, a report sync) touches the site's `last_seen_at`, debounced to at most one write per site per five minutes, and refreshes `plugin_version` when the site reports one. Previously both were only written by the daily re-verify, so an actively used site could show "Last seen 20h ago" and a freshly upgraded plugin kept its old version on the Overview card for up to a day.

v1.3.4

2026-09-20

The UCSS renderer no longer navigates away from the page it is measuring and

Added

New `strategy` on speed scans. `run_speed_scan` and `POST /sites/:id/speed-scan` pass `both` (default), `desktop` or `mobile` through to the scan engine, which now grades the desktop run as the headline and the mobile run alongside it; a single device costs half the engine's quota. The Hub's report screen names the run its grade came from.

Fixed

Fixed The renderer never navigates away from the page being measured. Interaction now skips anything that would navigate — an anchor with a real target, a submit, anything whose click bubbles to a link — and top-level document navigations are aborted outright after the initial load.
Fixed A page that never reaches network-idle no longer fails the render with a 504. The renderer settles on document readiness and a bounded quiet period instead of waiting forever for the network to go idle.
Fixed Admin console list tables scroll inside themselves,. not the whole page.
Fixed xCloud no longer rebuilds the admin console blank on every deploy. — the build carries its base path explicitly instead of relying on the environment.

v1.3.3

2026-09-17

Staff can now sign in as a customer to debug a ticket — time-boxed, read-only

Security

Fixed A case-variant URL no longer slips past the impersonation path block. Express matches routes case-insensitively, but the forbidden-path check compared exactly — so `/BILLING/portal` reached the billing handler from a write-enabled impersonated session while `/billing/portal` was refused. Both path comparisons (the forbidden list and the end-impersonation escape hatch) now lowercase before matching.
Fixed Rate-limit keys and audit IPs can no longer be spoofed. The Hub trusted every proxy hop and read the leftmost `X-Forwarded-For` entry — which the client writes — so rotating the header defeated the login and mail limiters, and audit rows recorded an attacker-chosen address. Express now trusts exactly the one nginx hop and `req.ip` is used everywhere.
Fixed CSV exports neutralize spreadsheet formulas. Customer-written values (emails, site URLs, workspace names) reach staff spreadsheets; a value starting with `=`, `+`, `-` or `@` would execute in Excel. Such fields are now prefixed with a literal-text apostrophe.
Fixed An impersonated session fails closed during a database blip. The guard allowed reads through when the session could not be verified; a session carrying the staff-stash cookie — which only exists during an impersonation — is now refused instead.

Added

New Staff can sign in as a customer to debug a problem. , when a support ticket cannot be answered any other way. It is off unless `XSPEED_HUB_ALLOW_IMPERSONATION=1`, superadmin-only, needs a recently re-authenticated browser session, and requires a written reason that is stored with the record. Sessions are read-only by default, stop working after 30 minutes — reads included — and can never reach billing or account deletion whatever the settings. The staff member sees a persistent banner naming the customer, the read-only state and the time left, with a one-click way out. The customer is not notified: the record lives in the audit log, which the console now surfaces as "Signed in as" beside the staff actions.
New Every staff action is now recorded. Changing a workspace's tier, revoking its tokens, reassigning an owner or removing a site writes a row to a new `admin_audit` table — actor, target, reason, IP and outcome, including refused attempts. None of it left any trace before. Metadata is redacted before storage, so a credential can never end up in the log.
New The admin console has a dashboard, a sidebar and real URLs. It gained sections for workspaces, sites, tenant activity and the audit log, each a linkable path that carries its search and filters — so a filtered view can be handed to a colleague rather than described to them. The dashboard adds active users, 24-hour tool-call volume and error rate, failed jobs and weekly signups alongside the existing counts.
New A reason is now required to change a workspace's tier. , and removing a site requires typing its URL back. Both used to happen on a single click.

Changed

Improved Admin lists are paginated, searched and sorted by the server. The console previously fetched *every* account and *every* site on load and filtered them in the browser; both queries were unbounded. Page size is capped server-side and sort columns are allow-listed.
Improved The console follows the current design system. — the same muted-teal tokens, self-hosted fonts and deep-sea rail as the account app, rather than the superseded blue. It carries an `ADMIN` badge so a screenshot is never mistaken for the customer-facing app.

Fixed

Fixed The admin site list no longer returns each site's decrypted token. `site_token` is decrypted in the repo layer, so the pre-existing list endpoint was serializing a live credential for every connected WordPress install into the response. It is now stripped, and a test asserts it stays that way.
Fixed The admin console is in CI. It had no job at all, so a broken console build could reach `main` — where it deploys from the same merge as everything else. `scripts/deploy.sh` gained the matching `admin` target.
Fixed The two database drivers now agree on admin searches and sorting. Under `DB_DRIVER=prisma`, a search for `100%` or `a_b` was treated as a wildcard and matched the wrong rows, and sorting by a nullable column such as `last_seen_at` put never-seen rows *first* instead of last — so page one was the sites nobody had heard from. Both now match the Postgres driver.
Fixed The audit log's search box works. It sent its term to the server, which parsed and then discarded it, so typing in it silently changed nothing.

Added (admin, phase 2)

Improved Staff access is graded rather than all-or-nothing. Four levels — read-only, support, admin, superadmin — so an analyst can be given visibility without the revenue lever, and a support engineer can end a session without being able to change what a customer pays. Previously anyone on the admin email list could do everything. `XSPEED_HUB_ADMIN_EMAILS` still works and always grants superadmin, on purpose: it is the way back in if the staff table is ever unreadable.
Improved Users are visible. A searchable list of every login identity, and a detail page showing which workspaces they belong to and at what role, which sites they can actually see, and where they are signed in — with buttons to sign them out everywhere or revoke their AI connections.
Improved Workspace detail. Members and their roles, sites, and live invitations in one place, with member roles editable.
Improved A staff page. , listing who has console access and who holds break-glass access through the environment variable — the latter shown explicitly, because those people hold no row and the table would otherwise look complete when it was not.
Improved Site troubleshooting without a database. A site's page now shows why it is failing — `last_check_error` was recorded on every failed check and never displayed — alongside plugin version, latency, which modules are on, 90 days of cache-hit and page-count history, and stored PageSpeed/GTmetrix scores. Test connection and Re-verify run from the console.
Improved A system page that says whether the Hub itself is healthy. Database latency and connection-pool pressure, which migrations have run, and what has failed in the last day — alongside the dependency probes. Plus a config view showing which variables are set, and deliberately nothing about what they contain.
Improved Workspaces and users can be deleted from the console. Previously this meant editing the database by hand. It is off unless explicitly enabled on the server, superadmin-only, and needs the name typed back, a reason, and a sign-in from the last half hour — because an unattended laptop should not be a standing licence to destroy data. What was deleted is recorded before it goes, so the log still names the sites and members afterwards. Deleting someone who solely owns a *shared* workspace is refused: it would strip access from people who never agreed to it.
Improved One AI credential can be revoked without touching the others. The console lists every connected client with its scopes and when it last did anything, and flags the ones nothing has used in ninety days — including those never used at all, which is access granted and never exercised. Previously the only option was signing out every client a person held.
Improved A page that says whether a failing job is our fault. PageSpeed, the GTmetrix runner, the CSS renderer, the scan engine and email each report configured and reachable, so "their site is down" and "our renderer is" stop looking identical.
Improved ⌘K search. One box resolves an email, a domain or a workspace name to the right page. A support conversation starts with one of those three, and this replaces working out which list to filter.
Improved The platform cannot be left without a superadmin. Demoting or revoking the last one is refused, and the check runs inside the same transaction as the write, so two people doing it at once cannot both succeed. Without this, a single demotion could leave nobody able to grant staff access — recoverable only by editing the database directly.

v1.3.2

2026-09-16

Password login joins Google and the magic link, the sign-in mail path stops

Added

New Email + password sign-in. Alongside Google and the magic link: sign in with a password, and "Create account / set password" doubles as password reset — the password activates only when the emailed confirmation link is clicked, so it also proves address ownership.

Fixed

Fixed A failed magic-link request now says so. When the database or SMTP was unreachable, the request crashed unhandled while the UI showed "check your inbox" — a customer sat on that silent failure. The route now answers 503 and the sign-in screen shows an honest retry message.
Fixed Auth mail is rate-limited. Magic-link and signup mail sends are capped per IP and per address, closing an open mail-relay hole.

Security

Fixed Password verification costs the same for a no-password account as for a wrong password, so response timing cannot enumerate accounts; scrypt runs off the event loop; the mailed-link log line no longer records the address; and password login honors the admin-console session invariant the other login paths state.

v1.3.1

2026-09-15

The UCSS/CCSS renderer can now run on our own server instead of only Cloud Run.

Added

New The renderer has a monitoring dashboard. `GET /dashboard?token=…` on the renderer shows totals, successful renders, errors, and requests-per-hour (from the nginx access log), plus in-process render durations; `GET /stats` serves the same numbers as JSON. Token-gated, and disabled entirely when no `RENDERER_TOKEN` is set.
New The UCSS/CCSS renderer can now run on our own server, not only Cloud Run. With `UCSS_RENDERER_URL` + `UCSS_RENDERER_TOKEN` set and no `UCSS_RENDERER_SA_KEY`, the Hub sends the app bearer directly and never contacts Google; a URL with no credential at all now configures nothing instead of calling the renderer unauthenticated. The self-hosted stack ships in `services/ucss-renderer/deploy/` — PM2 cluster + host nginx, the same shape the Hub runs as, scaled with `pm2 scale ucss-renderer N`.

v1.3.0

2026-09-14

A structural release. Nothing about the Hub behaves differently for anyone using

Changed

Improved The server, the MCP tool catalog and the SPA are organized into domain folders. `server.ts` and `tools.ts` had grown past the point where a route could be found by reading them. All 102 route paths and all 29 tool names are unchanged, as are their schemas and response shapes — this is code movement, not a rewrite.
Improved A Prisma-backed database driver ships alongside the pg driver. , selected by `DB_DRIVER=prisma` and verified at parity across the repo suite under both. It is opt-in: with the variable unset — as it is in production — the existing pg driver runs, unchanged. The schema is untouched and no migration is needed, so rolling back any Prisma trouble means leaving `DB_DRIVER` unset.

v1.2.9

2026-09-14

Critical CSS can now be generated from the Hub. The new `generate_critical_css` tool builds a site's above-the-fold CSS and stores it, so the first screen paints without waiting for the full stylesheets — the fix for a site whose LCP is slow because its stylesheets are still render-blocking. Previously this was reachable only from the site's own MCP connection or WP-CLI. The site applies the blob on its next page build, so purge the cache afterwards.

Added

New Critical CSS can now be generated from the Hub. The new `generate_critical_css` tool builds a site's above-the-fold CSS and stores it, so the first screen paints without waiting for the full stylesheets — the fix for a site whose LCP is slow because its stylesheets are still render-blocking. Previously this was reachable only from the site's own MCP connection or WP-CLI. The site applies the blob on its next page build, so purge the cache afterwards.
New `optimize_site` can now drive a site toward a target score. `target_score` (Pro sites only) turns the single pass into bounded rounds working toward that number. It is opt-in per call rather than defaulted — each round costs a real PageSpeed measurement and up to two minutes — and the rounds are budgeted inside the call, divided across a fan-out, stopping early when rounds stop helping (`stopped_because` says why). The tool's instructions now also tell the assistant to open the returned `verify_urls` in a browser before reporting success: the site-side safety checks read HTML and cannot execute JavaScript, so `verified: true` means the checks passed, not that the page works.

Fixed

Fixed A site whose token the site rejected is no longer kept. Adding a site that refused its token left an orphan row that looked connected and made every retry fail as a duplicate; the row is now dropped when the site answers that its token is invalid.
Fixed Re-pasting a token for a site you already have repairs it instead of answering 409. The repair runs only for members who could already administer that site — site grants are checked the way every other site-mutating route checks them, so a restricted member still gets the ordinary 409 and cannot overwrite the credential of a site they were kept out of.
Fixed Typing in a dialog with two inputs no longer jumps focus between fields. The shared modal re-ran its autofocus on every keystroke, so the first field stole focus mid-word. Add a site is where it bit, but every dialog with more than one input had the same bug.
Fixed The fold is now also measured on a widescreen desktop. The rendering service measured the first screenful across a 390&times;844 phone and a 1280&times;900 desktop; a rule that only paints above the fold at full-width desktop sizes was missed, so Critical CSS could defer a sheet a 1920-wide visitor needed immediately. The measurement now unions a 1920&times;1080 viewport in as well.

v1.2.8

2026-09-10

The rendering service now measures the fold, so Critical CSS can use it too. `POST /site/ucss/measure` already answered which selectors a page uses; it now also returns `critical` — the selectors painting in the first screenful, unioned across a 390&times;844 phone and a 1280&times;900 desktop. Critical CSS had no browser to ask, so it approximated the viewport by taking the first N opening tags of `<body>`: an ordinal count standing in for a layout fact. Whether a rule paints above the fold is a layout fact, and now something measures it.

Added

New The rendering service now measures the fold, so Critical CSS can use it too. `POST /site/ucss/measure` already answered which selectors a page uses; it now also returns `critical` — the selectors painting in the first screenful, unioned across a 390&times;844 phone and a 1280&times;900 desktop. Critical CSS had no browser to ask, so it approximated the viewport by taking the first N opening tags of `<body>`: an ordinal count standing in for a layout fact. Whether a rule paints above the fold is a layout fact, and now something measures it.

v1.2.7

2026-09-10

Unlisted scan reports are labelled in a site's report history. A site connected to the Hub asks the scan engine to keep its reports out of the public directory, and the Hub is the one place its owner still sees them — so the table says which rows are unlisted, and the note says what that does and does not promise: the report link still works for anyone it is shared with, so it is a secret link rather than a private page.

Added

New Unlisted scan reports are labelled in a site's report history. A site connected to the Hub asks the scan engine to keep its reports out of the public directory, and the Hub is the one place its owner still sees them — so the table says which rows are unlisted, and the note says what that does and does not promise: the report link still works for anyone it is shared with, so it is a secret link rather than a private page.

Fixed

Fixed A single licence refusal no longer locks a valid site out for an hour. One earlier refusal was cached and every request for the next hour read that instead of asking the store, so a key activated moments ago, an activation limit just raised, or a store that answered but wrongly each cost a paying customer an hour of local pruning with nothing to do but wait. Acceptances are still cached for an hour — the store is a third party on a hot path — but refusals now expire after a minute, and support can clear one outright without restarting the Hub.

v1.2.6

2026-09-04

Unused CSS is now measured in a real browser, not guessed from HTML. Pruning read the served markup, which cannot show what a page uses *after* someone interacts with it: a class JavaScript adds on click is absent from the markup in exactly the way a class no element ever carries is absent. A live pricing toggle broke on that — the rules that slide its knob and hide its inactive pane were pruned, leaving both panes showing and a dead switch. Three static heuristics were measured against the real stylesheet before this: each either lost a state or put ~40 KB of genuinely dead CSS back, because a state class and an unused widget variant are the same shape in HTML. `POST /site/ucss/measure` loads the page in Chromium, drives its own controls, and returns every selector used in either state. On the page that surfaced this it recovers all three broken rules for seven extra selectors out of 1772.

Added

New Unused CSS is now measured in a real browser, not guessed from HTML. Pruning read the served markup, which cannot show what a page uses *after* someone interacts with it: a class JavaScript adds on click is absent from the markup in exactly the way a class no element ever carries is absent. A live pricing toggle broke on that — the rules that slide its knob and hide its inactive pane were pruned, leaving both panes showing and a dead switch. Three static heuristics were measured against the real stylesheet before this: each either lost a state or put ~40 KB of genuinely dead CSS back, because a state class and an unused widget variant are the same shape in HTML. `POST /site/ucss/measure` loads the page in Chromium, drives its own controls, and returns every selector used in either state. On the page that surfaced this it recovers all three broken rules for seven extra selectors out of 1772.
New The renderer itself ships in `services/ucss-renderer/`. A separate Cloud Run service rather than a library in the Hub: Chromium's memory is unbounded in practice, and the Hub also serves MCP, the dashboard and billing — rendering in-process means one heavy page can take all of it down. Optional. With no `UCSS_RENDERER_URL` configured the route answers 503 and the plugin prunes locally, so the feature degrades rather than breaking.

Security

Fixed Measurement is gated on the site's Pro licence, verified against the store, rather than on a Hub pairing — a paid capability should not depend on an unrelated integration, and this is what WP Rocket's equivalent does too. A page must be same-origin with the licensed site: the renderer loads whatever URL it is handed, so an unchecked one would make this an open proxy wearing the service account. Measurements are capped per site per hour, keyed by site rather than licence so one busy site cannot exhaust an agency licence's other sites.

v1.2.5

2026-09-02

The in-Hub scan report now matches the xSpeed Scan report exactly. It leads with the site — favicon, host and the full-size score ring — instead of a bare grade, shows the page as the scanner saw it in both desktop and mobile with click-to-zoom, and carries the report's own section bar, dimension panels (grade chip, checks-passed count, points earned) and scan history. The acquisition blocks the public page carries are deliberately left out: whoever is reading this already owns the site and already has their Hub connection.

Changed

Improved The in-Hub scan report now matches the xSpeed Scan report exactly. It leads with the site — favicon, host and the full-size score ring — instead of a bare grade, shows the page as the scanner saw it in both desktop and mobile with click-to-zoom, and carries the report's own section bar, dimension panels (grade chip, checks-passed count, points earned) and scan history. The acquisition blocks the public page carries are deliberately left out: whoever is reading this already owns the site and already has their Hub connection.
Improved The headline tiles match the rubric. Seven readings in the report's order with its thresholds and colours, replacing nine that included two the report never tiled, and durations now print as `592ms` / `7.0s` the way the engine does rather than disagreeing below one second.

Fixed

Fixed A check the rubric marked "not applicable" no longer counts as a failure. `na` was missing from the status type, so an ungraded check sorted as unknown, entered the checks-passed denominator, and offered its points back as a top fix. A per-visitor page can now report 2/2 passed instead of 2/4.
Fixed `xspeedHub` is a tri-state boolean, not a string. The engine sends `true` / `false` / `null` (the last meaning the site's plugin is too old to say); the mistyped field made the "Hub attached" pill unreachable.

v1.2.4

2026-09-01

A report opens over the reports list instead of replacing it. Reading one is a look, not a departure: the list stays behind the dialog, so closing a report returns you to it with its device filter and comparison selection intact rather than reloading the tab. The report keeps its own URL, so it is still reloadable, still linkable, and the back button still closes it rather than leaving the site.

Changed

Improved A report opens over the reports list instead of replacing it. Reading one is a look, not a departure: the list stays behind the dialog, so closing a report returns you to it with its device filter and comparison selection intact rather than reloading the tab. The report keeps its own URL, so it is still reloadable, still linkable, and the back button still closes it rather than leaving the site.

v1.2.3

2026-09-01

Scan reports open inside the Hub. A scan result used to be a link that took you to xspeedcache.com; the grade, the four dimension scores, every check with its evidence and fix, and the screenshot now render on their own page in the Reports tab. The report keeps a shareable link and a Markdown twin for anyone who wants the public page, but reading your own site's report no longer means leaving the dashboard.

Added

New Scan reports open inside the Hub. A scan result used to be a link that took you to xspeedcache.com; the grade, the four dimension scores, every check with its evidence and fix, and the screenshot now render on their own page in the Reports tab. The report keeps a shareable link and a Markdown twin for anyone who wants the public page, but reading your own site's report no longer means leaving the dashboard.
New One reports table for every provider. The full website scan now sits beside PageSpeed and GTmetrix in the same list rather than in a separate card, and leads it — the scan engine is public, so it is the one provider that cannot be missing a key, and it grades the whole site where the others measure a single page.
New A report is its own URL. `/sites/:slug/reports/:reportId` is reloadable and linkable, and the back button steps out of the report rather than off the site.

Changed

Improved `GET /sites/:id/speed-scan/:scanId` accepts `?detail=full` for the whole graded audit and `?shots=1` for the screenshot and favicon. The default response is unchanged, so the MCP tools and the polling loop keep paying for only the condensed shape.

v1.2.2

2026-08-29

Full website reports, unified with xSpeed Scan. The Reports tab gains a "Full website report" card and the MCP catalog gains `run_speed_scan` / `get_speed_scan`: both queue the same graded scan engine that powers xspeedcache.com/scan (server probes + Lighthouse, four dimensions, every failing check ranked with its fix) and hand back the shareable report page. The website stays the single store of reports, so runs started from the Hub, the public /scan page, or a report's Re-scan button all land in one per-site history.

Added

New Full website reports, unified with xSpeed Scan. The Reports tab gains a "Full website report" card and the MCP catalog gains `run_speed_scan` / `get_speed_scan`: both queue the same graded scan engine that powers xspeedcache.com/scan (server probes + Lighthouse, four dimensions, every failing check ranked with its fix) and hand back the shareable report page. The website stays the single store of reports, so runs started from the Hub, the public /scan page, or a report's Re-scan button all land in one per-site history.

v1.2.1

2026-08-29

Autopilot now measures what it applied — and undoes a change that made the site slower. Each pass with something to apply takes a median-of-three uncached render-time baseline (the site measures itself, so Hub-side network variance never enters the number), re-measures after applying, and automatically replays the stored undo when the median regresses past both noise floors (30% and 150ms). Verdicts — better / unchanged / worse / unknown, with medians and spreads — land in the activity log, an unmeasured pass never triggers a blind revert, and a rule whose last application on a site was undone (by the measurement or by a person) is vetoed from re-applying automatically until someone applies it by hand.

Added

New Autopilot now measures what it applied — and undoes a change that made the site slower. Each pass with something to apply takes a median-of-three uncached render-time baseline (the site measures itself, so Hub-side network variance never enters the number), re-measures after applying, and automatically replays the stored undo when the median regresses past both noise floors (30% and 150ms). Verdicts — better / unchanged / worse / unknown, with medians and spreads — land in the activity log, an unmeasured pass never triggers a blind revert, and a rule whose last application on a site was undone (by the measurement or by a person) is vetoed from re-applying automatically until someone applies it by hand.

v1.2.0

2026-08-26

One AI connection can span several workspaces. An MCP connection used to be welded to the workspace it was created in — a member of three workspaces needed three connections, and the AI could never see past the one it was born into. Every site-scoped tool now takes an optional `workspace` argument, and `list_workspaces` shows which workspaces you belong to and what you are in each. Say "switch to Acme" and the assistant keeps working there, the same way it already stays on one site across follow-up questions.

Added

New One AI connection can span several workspaces. An MCP connection used to be welded to the workspace it was created in — a member of three workspaces needed three connections, and the AI could never see past the one it was born into. Every site-scoped tool now takes an optional `workspace` argument, and `list_workspaces` shows which workspaces you belong to and what you are in each. Say "switch to Acme" and the assistant keeps working there, the same way it already stays on one site across follow-up questions.
New The consent screen names the workspace you are connecting. It always used whichever workspace you were last in, without saying so; if you belong to more than one it now also lets you choose which the connection may reach. A connection reaches exactly what was ticked, and no tool call can widen it — adding a workspace means reconnecting.

Security

Fixed A call is authorized against the workspace it targets. The role that decides what a connection may do is resolved per call, in the workspace being acted on, so being an owner of your own workspace never grants write access to a client's. Removing someone from a workspace cuts their AI connection off from it immediately, even though the connection still lists it.
Fixed Changes to another workspace must name it. A write that would land outside a connection's default workspace is refused until the assistant says which workspace it means, so you can see which site is about to change.
Fixed Activity is recorded in the workspace it happened in, and a connection's call budget is now shared across every workspace it reaches rather than reset per workspace.

v1.1.2

2026-08-25

Owners can rename a workspace. Renaming was built everywhere except where anyone could reach it: the endpoint, the repo method and the client's `renameWorkspace` all shipped and worked, and nothing ever called the last one. So a workspace name was permanent once set, while the create dialog promised "You can rename it any time."

Fixed

Fixed Owners can rename a workspace. Renaming was built everywhere except where anyone could reach it: the endpoint, the repo method and the client's `renameWorkspace` all shipped and worked, and nothing ever called the last one. So a workspace name was permanent once set, while the create dialog promised "You can rename it any time."

Changed

Improved The connect config now names the MCP server `xspeedhub`. It read `xspeedcache-hub`, which is neither of the two things a reader is trying to tell apart — the `xspeed` plugin running inside one site, and the Hub sitting above many.

v1.1.1

2026-08-23

One press of Analyze now measures mobile and desktop in the background, and a notification bell, a snackbar and the browser tab itself tell you when the result lands. Newly attached sites are measured on arrival, and "Purge all" is on every screen.

Added

New One press now measures mobile and desktop, and tells you when it is done. An audit used to hold the request open until Google answered, which already sat a few seconds under the proxy's 60-second ceiling on a real WordPress page: and ruled out two devices entirely, since that is roughly ninety seconds. Audits are queued now: pressing Analyze answers immediately and the work continues in the background, so duration stopped being a constraint. Both devices run from one press, sequentially, and if one succeeds and the other fails the score that exists is kept with the failure reported beside it, rather than both being thrown away to report a clean failure.
New A notification bell, and status messages that follow you. The Hub could reach you by Slack and email but had nowhere to say anything inside the product, so work finishing minutes after the press that started it could only be seen by whoever was still watching the right tab. Audit results now land in a bell in the header, addressed to the person who pressed the button and readable from anywhere in the app, and a snackbar reports both the start and the finish with a link straight to the report. If you have switched to another tab by the time it lands, the tab itself tells you: the title carries an unread count and the favicon gets a dot, both only while the tab is in the background and both clearing the moment you come back.
New Newly attached sites are measured straight away, so a site's first score is already there rather than waiting for someone to find the Analyze button. Local sites are skipped, since PageSpeed cannot reach them.

Changed

Improved "Test" is now "Analyze" everywhere, and runs a real speed test. On the site row it sat beside a score ring and reported "cache on · 87% hit ratio". A configuration read wearing the name of a speed test; the same button on a site's own page had the same problem, and everything it reported was already on screen in the Live status panel below it. Both now measure PageSpeed on mobile and desktop, and the cache state is read where it was always shown.
Improved "Purge all" is on every screen now, and no longer styled as the page's primary button. It was limited to Overview and Sites, on the reasoning that it belongs with the screens it acts on: but clearing the cache is usually something you decide after doing something else, and having it disappear exactly then made it feel unreliable rather than focused. Dressing it as the main call to action, meanwhile, invited the stray click its confirmation dialog then has to catch, so it is now a secondary button.

Fixed

Fixed A stale run left behind by a restart is cleared within five minutes rather than up to an hour, so the Analyze button stops being blocked by work that is no longer happening.
Fixed The device control on the Reports tab is a real filter now. It sat above the run history looking like one, but only chose what the next audit would measure, so picking Desktop left every mobile row on screen. The table has its own filter, and the original keeps its actual job.
Fixed The last two native dropdowns were replaced with the app's own, so no control is painted in OS chrome any more.

v1.1.0

2026-08-19

The Hub now tells you when a site got slower, not just when a setting got turned off. Alerting watched three things — a site going unreachable, the cache being switched off, and the hit ratio falling through the floor — all of which describe configuration. A site could stay reachable, cached and healthy on every one of those and still have doubled its load time after a theme update, and nothing said a word. Performance regressions are now their own rules, over the report history already synced each day: the score, LCP, TBT, CLS and TTFB are each compared against a trailing median of recent runs, and a meaningful move in the wrong direction raises an alert down the existing Slack and email channels. Off until switched on per account.

Added

New The Hub now tells you when a site got slower, not just when a setting got turned off. Alerting watched three things — a site going unreachable, the cache being switched off, and the hit ratio falling through the floor — all of which describe configuration. A site could stay reachable, cached and healthy on every one of those and still have doubled its load time after a theme update, and nothing said a word. Performance regressions are now their own rules, over the report history already synced each day: the score, LCP, TBT, CLS and TTFB are each compared against a trailing median of recent runs, and a meaningful move in the wrong direction raises an alert down the existing Slack and email channels. Off until switched on per account.
New Autopilot: the Hub can now close the low-risk gaps itself, instead of waiting for someone to open the dashboard and click. Boost opportunities already found the problems and could fix them with a button, but only for whoever was looking — so a fleet drifted between visits, and a cache switched off during a debugging session stayed off until somebody noticed. The daily pass is already visiting every site; it now applies the fixes an account has explicitly authorised.
New Client-ready performance reports, on a link you can send someone outside the Hub. The people running many sites through one Hub are usually agencies, and their recurring job is showing a client that the money was worth spending. Everything needed for that was already stored — the audit history, the daily snapshots, the log of what was changed — but none of it could leave the dashboard in a form a client could read. A report can now be minted for any site over any period and handed over as a plain link, with the agency's own name and logo on it rather than xSpeed's.

Changed

Improved The Sites list now shows how fast each site is, not just that it exists. It listed a name, a URL and a latency while the Overview ranked the same sites by PageSpeed score — so the two screens showed the same fleet and read as different products, and deciding which site needed attention meant going back to the Overview. Each row now carries that site's score, its Free/Pro tier, and what the score could reach once its queued fixes are applied, with one device toggle for the whole list. The heading counts what has already been won and what is still on the table.

Fixed

Fixed Scores now appear with their sites instead of a moment later. The list came from one request and the scores from another, and the second was not started until the first came back — so the page painted a flat list and then visibly re-flowed as rings, tier badges and estimates dropped in and pushed the names sideways. Both requests now start together and the list waits for both, the way the Overview has always worked. If the scores cannot be fetched at all the list still appears without them, rather than holding an empty screen.
Fixed A score ring no longer reads as a letter. The unfilled part of the ring was drawn in a surface colour a few percent off the row behind it — invisible at small sizes, and gone entirely on a row highlighted under the cursor, which left a bare arc that looked like a letter rather than a gauge. It now uses the border colour, which stays visible against both. This also sharpens the rings on the Overview, where the same track was fainter than intended.
Fixed A section heading no longer collapses to one word per line on a phone. Buttons beside a title took the width they needed and left the title the remainder; on a narrow screen that remainder was thinner than a single word, and the last button was pushed off the edge of the screen. Headings and their buttons now stack below 640px, which also fixes the Members and Profile screens.

Security

Fixed The Hub's database is no longer reachable with the project's anon key. Supabase's default grants were never revoked and row-level security was never enabled in `schema.sql`, so the `anon` and `authenticated` roles held full read/write on all 18 public tables. Nine of them — including `users`, `account_members`, `invitations` and `site_members` — had RLS off entirely, making them readable and modifiable by anyone holding the project's anon key through the project URL alone; the other nine were shielded only by RLS defaulting to deny. The Hub talks to Postgres directly as a `BYPASSRLS` role and never uses PostgREST or supabase-js, so enabling RLS with no policies closes this without touching the application. The grants are revoked and default privileges altered too, so tables added later can't inherit the same hole. Verified on production: no table without RLS, none reachable by `anon`/`authenticated`, application access unchanged.

v1.0.12

2026-08-16

"Make my site fast" is now a single call that measures, applies one change at a time, and puts back anything that broke the page. The Overview shows what each score could reach and what is already going well, and speed tests started from an assistant actually run.

Added

New "Make my site fast" is now one call. Every individual action already existed. Turn caching on, minify, warm the cache, run a speed test: but deciding which to use, in what order, and whether the site still worked afterwards was left to the assistant. optimize_site runs the whole sequence deterministically: it measures, applies one setting at a time, re-checks the page after each, and puts back anything that broke it. It reports what it applied, what it undid and why, and what it could not reach at all.
New The Overview shows what each score could reach, not just what it is. Each site now carries a reachable score beside its current one, and each recommendation the estimate of what it would gain. Deliberately conservative: an estimate appears only where the fix actually reaches what Lighthouse measures, and a projection takes the largest gain plus half the rest rather than adding them up.
New The Overview shows what went right, not only what is broken. Three win cards surface crossings of 90, month-over-month gains and healthy streaks, all derived from snapshots the daily pass already collects. A win has to be earned to appear, and when nothing qualifies the row renders nothing rather than padding with encouragement.
New Fleet scores now lead with desktop, with a toggle for mobile. One control switches the whole section, and the score bar is banded so a number reads as good or bad at a glance.
New The Hub now has a favicon. Both the account app and the admin console carry the xSpeed brand mark, as an SVG that stays sharp at every size, with a PNG fallback and an apple-touch icon for iOS home screens.

Fixed

Fixed "Sites, worst first" now actually is worst first. The order came from a composite health score that never read the PageSpeed number at all, so a site scoring 94 on a thin hit ratio ranked above one scoring 43 at 99%, directly under a column showing those very scores. Untested sites now sort last rather than first.
Fixed A red score is no longer labelled "Healthy". The pill meant "no open recommendations", which is not the same thing. A site can satisfy every cache rule and still be slow behind a 12.6s LCP. It now stands down unless the score agrees.
Fixed Speed tests started from an AI assistant now run. The tool was asking the WordPress site to run the audit and report back, so it needed a plugin new enough to know the tool and a successful fetch of the Hub's PageSpeed key; when either failed the site called Google unkeyed and hit the shared rate limit. The Hub now runs the audit itself, exactly as the dashboard does.

v1.0.11

2026-08-13

Settings edits save themselves and survive a reload, each settings group is its own searchable page, and an AI assistant can finally run a speed test, not just read old ones.

Settings

Improved Settings edits now save themselves. A write travels from the Hub to the site's own API and back, and on a slow site that wait was the user's problem: the Save button sat disabled, and two edits made in quick succession could land out of order, leaving the older value on the site. An edit now takes effect locally the moment it is made and is sent a moment later, with only one write per module in flight at a time, so they cannot overtake each other. A change that has not reached the site yet is kept: through a reload, a closed tab, or a site that is temporarily down: and retried, and a value the site would reject is refused with the reason shown against the field rather than being sent and failing. Two browser tabs open on the same settings can no longer overwrite each other's work.
Improved A site's settings are now one page per group, and searching narrows them in place. The Settings tab rendered all seven groups stacked in a single column, 34 modules and 130-odd settings, so Cache ran into Optimization ran into Network and the only way through was scrolling. Each group is now its own page at /sites/<site>/settings/<group>, which means a group is linkable, survives a reload, and the back button steps between groups. Searching keeps that layout rather than replacing it: the group list stays where it is and its counts become a live tally of where the matches are, each module shows only the settings that matched with the rest a click away under "show all", and the matched text itself is marked.

Speed tests

New An AI assistant can now run a speed test, not just read old ones. Asking Claude to test a site's speed previously went nowhere: the Hub offered get_score_history, which reads past audits, and nothing that could start one, so an assistant correctly reported it was unable to help and pointed users back at the dashboard. The new run_speed_test tool runs a real Lighthouse audit (PageSpeed Insights, or GTmetrix where a site has it configured) and returns the score with Core Web Vitals. It is a write tool: it spends the Hub's shared PageSpeed allowance and stores a run, so a read-only connection cannot call it.
Fixed An assistant asked for a PageSpeed score no longer answers with the cache benchmark. The two measure different things: a real Lighthouse score versus xSpeed's own cached-vs-uncached TTFB: and nothing in the guidance said so, so the wrong tool looked like a reasonable answer. The connection instructions now contrast them by name and tell the assistant to read existing history before spending a new run.

Connection instructions

Improved The read/write tool lists in the MCP connection instructions are now derived from the catalog rather than typed out by hand. Every hand-written list had already gone stale, none mentioned the Cloudflare, object-cache or score tools, and a tool missing from the instructions is effectively invisible, because the model reads them before it reads the catalog.

v1.0.10

2026-08-11

Run a PageSpeed audit from the Hub on the device you choose, let your AI purge Cloudflare and diagnose the object cache, and find any setting in a grouped, searchable Settings tab.

Reports

New Run a PageSpeed audit from the Hub, on the device you choose. The Analyze button on a site's Reports tab now runs PageSpeed Insights against the site and stores the result beside its history: desktop by default, mobile a click away, and each kept as its own run so the two can be compared. Previously the Reports tab could display a PageSpeed run but had no way to start one. Which providers the tab offers is now a server setting, so a Hub can present PageSpeed alone, GTmetrix alone, or both; with one provider the chooser disappears rather than becoming a control with a single option, and the remaining monthly count is shown only for GTmetrix, which is the one that has a limit.

AI actions

New Your AI can now check and fix a site's Cloudflare cache. Purging a site's own cache while Cloudflare still serves the old page is a confidently wrong answer, and it was the only thing an assistant could do. It can now purge the edge, check that the stored credentials still work, and turn development mode on or off, with the caveat that development mode slows the site for real visitors while it is on, so the assistant is told to turn it back off.
New Your AI can now diagnose the object cache. An object-cache drop-in left pointing at a backend that is gone adds seconds to every request: the site stays up, the page cache looks healthy, and nothing else explains it. An assistant can now open a live connection to Redis or Memcached and report what came back, alongside reading the cache's state, flushing it, and turning it on or off. Asked why a site is slow, it can now answer that question instead of ruling out everything else.

Settings

New The site Settings tab is grouped and searchable. It listed every module a site reports as one flat alphabetical accordion, around 46 rows on a site running Pro. Settings now sit in the same seven groups the plugin's own dashboard uses, with a jump list and a search that matches a module's name or any individual setting's label, description or options: typing ttl finds the four modules that have one, webp finds the image-format settings.

Connections

Improved The connect config now names the server xspeedcache-hub instead of xspeed, so you can tell which xSpeed it is. The plugin exposes an MCP server on every site it runs on, so a config often holds several at once: and when they were all called xspeed, neither you nor the AI could tell from a tool call whether it reached the Hub or one particular site. That ambiguity mattered most for the calls that change something, like purging a cache or updating settings. Tools now appear as mcp__xspeedcache-hub__*. Existing connections keep working under the old name and pick up the new one the next time a fresh config is pasted, such as after rotating a token; the name is client-side only, so renaming it yourself is safe.

Boost opportunities

Fixed A boost opportunity for a feature you already run no longer shows an "Enable" button that does nothing. The button was drawn from whether the module could be switched, never whether it already was: so a suggestion naming a running feature offered to enable it, saved successfully, and changed nothing visible. Such a suggestion now reads as advice. The matching plugin-side fix stops the audit raising those suggestions in the first place.

v1.0.9

2026-08-11

One AI request now reaches the whole fleet, each site page carries its own Pro audit with one-click fixes, modules toggle straight from the site overview, and the Hub picks up the finalised xSpeed mark.

Fleet actions

New One AI request now reaches every site, "purge all my sites" is a single call. The site argument on purge_cache, toggle_cache, update_settings, run_benchmark and the preloader tools accepts "all" or a list of handles, and the result comes back per site: four sites where one is unreachable is reported as exactly that, never a blanket "done" or "failed". Sites run one at a time with the same courtesy pause the daily pass uses, a restricted connection asking for "all" quietly gets only the sites it's allowed to touch, and every site's action lands in the activity log as its own row. A four-site purge reads as four purges. The connection instructions teach the AI the new form, including confirming once before a fleet-wide write.

Site pages

New A site's page now shows its own Pro audit, merged with the Hub's advice. The plugin has always computed a personalized list of Pro features that would benefit each site (the same one its own dashboard shows); the Hub proxied it for AI clients but never displayed it, so the two surfaces gave one site different advice. A Boost opportunities panel on the site page now shows both in one list: deduplicated, with the site's items tagged "from this site". Suggestions that map to a switchable module get a one-click Enable; ones that need a Pro plugin the site demonstrably does not have get an honest Included in Pro link instead of a dead button. When the Hub cannot yet tell whether Pro is installed. The state every site is in until its first daily pass. The suggestion stays as plain advice rather than guessing, so a site that already runs Pro is never pitched an upgrade. Fetched only when the panel is opened, so the fleet Overview still costs zero live calls.
New Flip a module on or off from the site overview. The Modules card's chips are now switches: click one to enable or disable that module on the live site, with no settings form in between. Only modules whose own schema says they can be toggled get a switch: everything else (and everything, for viewers) stays a read-only chip, and the write goes through the same validated settings path the Settings tab uses. The chip flips immediately and flips back with the site's own explanation if the site refuses.

Branding

Improved The Hub now carries the new xSpeed Cache mark. The sidebar rail, the sign-in screen, the workspace switcher and the email logo all pick up the finalised branding. The artwork is the same two-path icon the plugin ships, so the Hub and the plugin stay pixel-identical rather than drifting apart.

v1.0.8

2026-08-09

The Overview becomes a fleet command center, a fleet-average score hero, an Apply-all button, and a worst-first site leaderboard.

Overview

Improved The Overview is now a fleet command center. A hero card leads with the fleet's average mobile score, a gauge showing the climb to the 90+ "good" band, and one Apply all button that runs every one-click fix in the queue: sequentially, with whatever's left after a failure still listed below. The site cards underneath became a worst-first leaderboard: one ranked row per site, each carrying that site's own top fix: so ten sites read as a list you scan, not a wall you hunt through. Single-site accounts keep their site hero unchanged.

v1.0.7

2026-08-09

Run a GTmetrix test on any site straight from the Hub, and every site now opens as its own linkable page.

Reports

New Run a GTmetrix test on any site straight from the Hub. A Test button on a site's Reports tab measures it there and then, instead of asking you to go and run one from that site's own dashboard. Results land in the same history as everything else, so a fresh test can be compared against any earlier run. Free accounts get 5 tests a month, Pro 50. The count is shown next to the button.
New The test works on every attached site, including ones whose owner has never configured GTmetrix, because it runs on the Hub's own account. The daily pass still only ever copies what a site already measured, nothing on a schedule spends anyone's credits.

Site pages

Improved Each site now opens as its own page at /sites/<handle>, instead of expanding an accordion inside the list. That address is linkable, bookmarkable and survives a reload, and browser back/forward moves between the list and a site the way you'd expect. The page carries four tabs. Overview, Settings, Reports and Access: each with its own address (/sites/acme/settings), so a tab can be shared too. The list row keeps what you scan a list for: name, URL, status and latency.
Improved Only the site you're looking at talks to your WordPress install. Several rows could previously be expanded at once, each proxying calls to a different customer site; one site at a time is now structural rather than a convention.

v1.0.6

2026-08-09

Overview reads clearly before your sites have any speed tests, and a connected AI client no longer fills the page with setup instructions you've already used.

Overview

Improved A site with no speed tests still looks designed. The mobile and desktop rings stay in place, muted, with an em dash, so the card keeps its shape, with one line underneath: "No speed tests yet · set up in site settings".
Improved The badge on each site card now means one thing: the connection. It appears for sites that are pending, unreachable, or revoked. Performance is already shown by the ring colours, the "N to fix" chip, and worst-first order.
Improved A connected AI client collapses to a single status line, "AI connected · claude-code · last call 19m ago". The connection snippets are one click away under Add a client / manage; before you've connected, that panel leads the page.
Improved Fleet score, Needs attention, and Open fixes share one compact strip instead of four large cards, and it's hidden entirely when you have one site. Boost opportunities are one line each, with the full explanation on hover. The hero drops its duplicate hit-ratio bar, the hit-ratio stat now shows the trend arrow inline.

Cache & health

New Purge a cache from the dashboard: one site, or the whole fleet. Until now purging was reachable only by an AI through MCP. A Purge all button sits in the top bar and each site row gets a Purge. The fleet purge confirms first, runs at most four sites at a time so it never becomes a thundering herd at customer origins, and reports per site: a fleet where one site is unreachable is a partial success, not a single "done" or "failed". Every purge is recorded in the activity log as its own row.
New Health diagnostics per site, and a config-issue signal on the fleet. The site drill-down now has a Health panel listing every check worst-first with the site's own explanation, plus its 30-day hit-ratio line against the 80% target. It is fetched only when opened, because it is a live call to the customer's server. The daily pass now records how many checks fail or warn, so a site with a broken environment carries a "config issues" chip on the Overview. A site the pass could not reach stores null, never 0. "we could not ask" must never read as a clean bill of health.

Preload & benchmarks

New Preload and warm a site from the Hub. The site drill-down now has a Preloader panel: start a crawl, watch it progress, stop it mid-run. It polls only while a crawl is actually running, so an idle preloader costs the customer's server nothing. When the site refuses because its preloader module is disabled, its own sentence is shown as a 409 rather than a generic failure.
New Three preloader tools on the MCP catalog: get_preloader_status (read), start_preloader and stop_preloader (write), so an AI can warm a cache after a purge. The Hub parses the plugin's CLI-transcript output defensively: every field degrades to null on its own, and an unknown running state renders as "unknown" rather than "idle".
New Benchmarks you can run from the Hub, and that stick around. The site drill-down now has a Benchmark panel; each result is kept in a new history alongside every previous run, so you can see whether a change actually helped. The headline is the time saved per request, with uncached and cached shown side by side so the number is checkable. A run taken with caching off has no saving (null, never 0), and a negative saving is kept and labelled "cached was slower" rather than clamped away.

v1.0.5

2026-08-06

The account app now looks like the plugin, and the Overview answers the question people open it for: how fast are my sites? Scores, hit ratio, and traffic lead the page.

Design

Improved The account app wears the plugin's redesign-v2 skin: the muted-teal accent, the deep-sea sidebar rail (dark in both themes), paper/panel/line surface tokens, self-hosted Inter + Space Grotesk + JetBrains Mono, 12px cards and pill badges. Every colour rides a CSS variable, so light and dark stay correct without per-class dark variants.

Overview

Improved Overview is now a fleet performance dashboard. One site gets a hero: big PageSpeed-style mobile + desktop score rings (Lighthouse's 0–49 / 50–89 / 90–100 bands), hit ratio, 24h requests, cache size, Free/Pro tier badge. Two or more sites get worst-first site cards plus a fleet stat strip (average mobile score, sites needing attention, open fixes). Scores come from each site's own stored PSI/GTmetrix runs, the Hub still never spends anyone's audit quota. Recommendations are reframed as "Boost opportunities", driving "N to fix" chips on the site cards.

AI & data

New Sites now report whether xSpeed Pro is active (inferred from the module list the daily pass already fetches) plus 24h hit/miss counts on each snapshot; the fleet endpoint carries them along with the latest stored mobile/desktop scores per site.
New Three read tools on the MCP catalog, get_health (env checks, hourly buckets, 30-day hit-ratio series), get_benchmark_history, and get_score_history, proxied 1:1 to the plugin tools that already exist, so an AI client can answer "how is my site doing" from one call.
Fixed Every module showed "Inactive" in the site detail view. Enabled state lives inside each module's own settings (settings.enabled); the Hub read a top-level enabled key the plugin never sends.

v1.0.4

2026-08-04

Team invitations now work end to end, the accept link, the email, and the invitation message are all fixed.

Teams

Fixed The emailed invitation link now lands on the accept screen instead of dropping the invitee on their own dashboard with the invitation still pending.
Fixed The invited email address now prefills on the sign-in screen.
Fixed Invitations now name the workspace you are being invited to, instead of repeating the owner's email address.
Fixed The logo in every email now renders instead of showing a broken image.

v1.0.3

2026-08-02

Scoped connections, one AI credential no longer means full control of everything, plus a speed-test history per site.

Access Control

New Scoped connection tokens. A connection can be read-only, limited to selected sites, and refused individual tools.
New Per-site access levels. Each site is Full access, Read-only, or No access, set as a default plus exceptions so a hundred sites is one decision.
New Edit a live connection's scope without reconnecting, tighten a credential without re-pasting config into every AI client.
Improved Restrictions only ever narrow access: reach is the intersection of the credential's limits and the member's role, and rotating a token preserves its scope.
Fixed A read-only connection is no longer described as full access on the Connect panel.

Reports

New Per-site report history. PageSpeed Insights and GTmetrix runs listed on the site drill-down, with any two comparable side by side across score, LCP, TTFB, FCP, TBT, Speed Index, and CLS.
Fixed A failed audit no longer stores a zero, missing metrics now read as unknown instead of claiming a perfect or catastrophic result.

v1.0.2

2026-07-31

Teams. One account becomes many people with different powers, and the account itself becomes a workspace you can name, create, and delete.

Teams & Workspaces

New Team & multi-user access, invite people as Owner, Admin, or Viewer, at account level and per site, with a Members section for people, roles, and pending invites.
New Roles are enforced everywhere, including the AI surface. A Viewer can read the fleet but cannot change settings, mint tokens, or write through an AI client.
New Workspaces, name, create, switch, and delete accounts, with a switcher in the sidebar.
New Per-site access, restrict a site to specific members for the "this contractor only touches one client" case.
New Profile page and confirmation prompts on every destructive action.
Fixed Loading the Connect page no longer auto-mints an account-wide read+write token. Minting is an explicit owner-only action.
Fixed Every AI tool now declares read or write access at registration, so a new write tool can no longer silently inherit write access.

v1.0.1

2026-07-30

Security hardening, a server-authoritative site cap, and a rebuilt deploy pipeline with automatic rollback.

Security & Reliability

Fixed Site tokens are now compared in constant time, closing a timing side-channel.
Fixed The site limit is now server-authoritative, so the add-site form no longer stops at a stale client-side cap.
Improved Releases now ship on a version tag, build in CI rather than on the server, and roll back automatically if the health check fails.

v1.0.0

2026-07-28

Initial release. Connect all your WordPress sites running xSpeed Cache and let one AI connection manage caching across the whole fleet.

Fleet Management

New Fleet overview ranking every site worst-first, with health chips and a site drill-down showing live cache status, modules, and trends.
New Remote settings editing, validated against each site's live schema.
New Fleet-wide recommendations center, a ranked next-best-action queue with one-click remote fixes.

AI & Monitoring

New MCP broker, one endpoint, one credential, every connected site reachable from Claude or any MCP-compatible AI client.
New OAuth 2.1 authorization server with per-site token scoping.
New Daily monitoring snapshots with Slack and email alerts, plus an activity audit log across account tool calls.
Hosted service

What is xSpeed Hub?

xSpeed Hub is the hosted companion to the plugin: connect every WordPress site running xSpeed Cache to one free account, monitor the whole fleet from one dashboard, and give your AI assistant a single MCP connection that reaches all of them.

The Hub ships by deploying: versions here record what is live on app.xspeedcache.com, updated for everyone at once.

Open xSpeed Hub

Make your site load in milliseconds.

One switch. Zero bloat. Always free to start.