Skip to content

Premium Analytics: dashboard on core Gutenberg packages (@next) - #49793

Merged
retrofox merged 21 commits into
trunkfrom
try/pa-core-packages-symlink
Jun 22, 2026
Merged

Premium Analytics: dashboard on core Gutenberg packages (@next)#49793
retrofox merged 21 commits into
trunkfrom
try/pa-core-packages-symlink

Conversation

@retrofox

@retrofox retrofox commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

What?

A customizable widget dashboard in premium-analytics, built on the core Gutenberg packages from npm @next (@wordpress/widget-dashboard, @wordpress/widget-primitives) — with no Gutenberg plugin requirement at runtime.

It also adds the host-side pieces Gutenberg leaves to the consumer: the widget-type registry, /jetpack/v4/widget-modules plus its widgetModule core-data entity, and the /jetpack/v4/dashboards/{name}/default-layout backend.

Why?

@wordpress/widget-dashboard reaches private component APIs (the actions Menu, the command palette) through @wordpress/private-apis, which gates them behind an allowlist of consenting module names.

WordPress core ships a private-apis whose allowlist does not cover the newer dashboard packages, so historically only a Gutenberg plugin checkout provided a complete-enough allowlist.

Requiring Gutenberg beside the repo made the dashboard impractical to ship.

How?

wp-build-polyfills now provides the runtime @wordpress/private-apis itself.
When core's bundled version is incomplete (WP < 7.1) and Gutenberg is not active, the package force-replaces the wp-private-apis script handle with a strict superset build whose allowlist covers the dashboard packages (@wordpress/widget-dashboard, @wordpress/ui, @wordpress/admin-ui, @wordpress/dataviews, @wordpress/route, …).

The polyfill bundles @wordpress/private-apis straight from npm, so its allowlist is exactly the published one. It now tracks the @next dist-tag (matching the dashboard packages).

That is what closes the last gap: the @next private-apis allowlist includes @wordpress/widget-dashboard, whereas the previously-resolved 1.48.1 did not. That mismatch threw at bundle init (__dangerousOptInToUnstableAPIsOnlyForCoreModules rejects an unlisted module) and aborted the SPA before any widget rendered.

Net result: the dashboard runs on core packages with no Gutenberg plugin, no docker Gutenberg mount, and no composer/plugin dependency.

Testing

pulls @wordpress/* @next, incl. private-apis @next

pnpm install
jetpack build packages/wp-build-polyfills
jetpack build packages/premium-analytics
jetpack docker up

Open the Premium Analytics dashboard in wp-admin (?page=jetpack-premium-analytics). No Gutenberg activation needed; widgets render and the date-range / comparison menus (private Menu) work.

Runtime sanity check (browser console on the dashboard page) — the polyfill's allowlist now accepts the dashboard packages:

const consent = 'I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.';
window.wp.privateApis.__dangerousOptInToUnstableAPIsOnlyForCoreModules( consent, '@wordpress/widget-dashboard' ); // no throw

Broader wp-build-polyfills regression coverage

Because this PR changes the shared wp-build-polyfills package, also verify that other Jetpack wp-build admin pages still load when their route bundles depend on wp-private-apis, wp-theme, @wordpress/boot, and @wordpress/route.

Note

This testing matrix was derived by GPT 5.5 as a result of prompting to investigate the usage of the packages polyfilled by the wp-build-polyfills package and surfacing the relevant user facing UI/UX impacted by the changes. If when testing, you find incorrect/incoherent instructions - update this list.

Recommended environment matrix:

  1. WordPress 7.0, Gutenberg inactive.
    • Expected: wp-private-apis is served by the Jetpack polyfill, and the dashboard packages can opt in without throwing.
  2. WordPress 7.0, Gutenberg active below the verified threshold, for example Gutenberg 23.4.0.
    • Expected: wp-private-apis is still served by the Jetpack polyfill. Gutenberg 23.4.0 and older do not have the private-apis allowlist entry needed by @wordpress/widget-dashboard.
  3. WordPress 7.0, Gutenberg 23.5.0 or newer active.
  4. WordPress trunk / 7.1-alpha, Gutenberg inactive.
    • NOTE: Edit the version so it strips the -alpha ( needed as 7.1-alpha is still seen as below 7.1 ):
   docker exec jetpack_dev-wordpress-1 \
  sed -i "s/^\$wp_version = '[^']*';/\$wp_version = '7.1';/" \
  /var/www/html/wp-includes/version.php
  • Expected: Core provides a complete enough wp-private-apis; the polyfill does not unnecessarily replace it.

The key threshold to verify is GUTENBERG_PRIVATE_APIS_MIN_VERSION = '23.5.0': test one Gutenberg version below that threshold and one at or above it, because the replacement logic intentionally treats those cases differently. Since there is not yet a Gutenberg 23.5.0 tag, use Gutenberg trunk containing WordPress/gutenberg#79268 / cbf74db259d for the at-or-above-threshold test.

For each environment, open the following wp-build-backed screens and confirm the page renders, route navigation works, and the browser console has no missing script/module errors or __dangerousOptInToUnstableAPIsOnlyForCoreModules allowlist errors:

  • Premium Analytics: wp-admin/admin.php?page=jetpack-premium-analytics
    • Confirm the dashboard route loads, widgets render, the Add widget modal opens, and date-range / comparison menus work.
  • Forms: wp-admin/admin.php?page=jetpack-forms-responses-wp-admin
    • Confirm the Forms and Responses routes load, filters/search work, and opening a response detail does not break the inspector panel.
  • Backup: wp-admin/admin.php?page=jetpack-backup
    • Confirm the dashboard, download, and restore routes load.
  • Social: wp-admin/admin.php?page=jetpack-social
    • Confirm Overview and Settings tabs load and the connection-management UI is usable.
  • Newsletter: wp-admin/admin.php?page=jetpack-newsletter and wp-admin/admin.php?page=jetpack-subscribers
    • Confirm the settings/subscribers tabs load and subscriber detail or announcement UI can open.
  • VideoPress: wp-admin/admin.php?page=jetpack-videopress
    • Confirm Overview, Library, Video, and Settings route navigation works.
  • SEO: wp-admin/admin.php?page=jetpack-seo
    • Confirm Overview, Settings, Content, and AI routes load, including the Content inspector.
  • Scan: wp-admin/admin.php?page=jetpack-scan
    • Confirm Active threats and History tabs load.

Runtime checks from the browser console on at least the Premium Analytics and one non-Premium Analytics wp-build page:

const consent = 'I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.';
window.wp.privateApis.__dangerousOptInToUnstableAPIsOnlyForCoreModules( consent, '@wordpress/widget-dashboard' ); // no throw
window.wp.privateApis.__dangerousOptInToUnstableAPIsOnlyForCoreModules( consent, '@wordpress/route' ); // no throw

When testing the Gutenberg-version threshold, also confirm the registered script source matches the expected provider:

  • WP 7.0 + no Gutenberg: wp-private-apis should point at jetpack-wp-build-polyfills.
  • WP 7.0 + Gutenberg < 23.5.0: wp-private-apis should still point at jetpack-wp-build-polyfills.
  • WP 7.0 + Gutenberg >= 23.5.0: wp-private-apis should remain Gutenberg-provided. Until a 23.5.0 tag exists, verify this with a Gutenberg trunk build containing Widget Dashboard: extract into @wordpress/widget-dashboard WordPress/gutenberg#79268 / cbf74db259d.
  • WP trunk / 7.1-alpha ( forcing the version number to 7.1, see script below ) + no Gutenberg: wp-private-apis should remain Core-provided.
   docker exec jetpack_dev-wordpress-1 \
  sed -i "s/^\$wp_version = '[^']*';/\$wp_version = '7.1';/" \
  /var/www/html/wp-includes/version.php

Targeted automated checks:

jetpack test php packages/wp-build-polyfills
jetpack build packages/wp-build-polyfills
jetpack build packages/premium-analytics
jetpack build packages/forms
jetpack build packages/backup
jetpack build packages/newsletter
jetpack build packages/publicize
jetpack build packages/scan
jetpack build packages/seo
jetpack build packages/videopress

Follow-ups

  • Decouple the polyfill's allowlist from the published private-apis version — ship its own curated superset, or add a CI check asserting the built CORE_MODULES_USING_PRIVATE_APIS ⊇ every opt-in name used by the bundled packages — so a future @next package can't reintroduce the gap.
  • Drop the polyfill once core ships a private-apis whose allowlist covers the dashboard packages (or once upstream replaces those private APIs with public components).
image

retrofox added 2 commits June 19, 2026 12:34
Layer the Gutenberg-linked dashboard (WidgetDashboard + local layout/grid hooks + widget registry + default-layout) onto premium-analytics, replacing the placeholder dashboard. Link @wordpress/{widget-dashboard,widget-primitives} to the local Gutenberg trunk worktree (gutenberg-midnight). Trunk's Sync/connect/syncing/REST untouched.
@retrofox retrofox self-assigned this Jun 19, 2026
@retrofox retrofox changed the title Premium Analytics: dashboard on core Gutenberg packages via local symlinks [DO NOT MERGE] Premium Analytics: dashboard on core Gutenberg packages via local symlinks Jun 19, 2026
@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • ✅ Add a "[Status]" label (In Progress, Needs Review, ...).
  • 🔴 Add testing instructions.
  • 🔴 Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖


🔴 Action required: Please include detailed testing steps, explaining how to test your change, like so:

## Testing instructions:

* Go to '..'
*

🔴 Action required: We would recommend that you add a section to the PR description to specify whether this PR includes any changes to data or privacy, like so:

## Does this pull request change what data or activity we track or use?

My PR adds *x* and *y*.

Follow this PR Review Process:

  1. Ensure all required checks appearing at the bottom of this PR are passing.
  2. Make sure to test your changes on all platforms that it applies to. You're responsible for the quality of the code you ship.
  3. You can use GitHub's Reviewers functionality to request a review.
  4. When it's reviewed and merged, you will be pinged in Slack to deploy the changes to WordPress.com simple once the build is done.

If you have questions about anything, reach out in #jetpack-developers for guidance!


Jetpack plugin:

The Jetpack plugin has different release cadences depending on the platform:

  • WordPress.com Simple releases happen as soon as you deploy your changes after merging this PR (PCYsg-Jjm-p2).
  • WoA releases happen weekly.
  • Releases to self-hosted sites happen monthly:
    • Scheduled release: July 7, 2026
    • Code freeze: July 6, 2026

If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack.


Backup plugin:

No scheduled milestone found for this plugin.

If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack.


Social plugin:

No scheduled milestone found for this plugin.

If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack.


Videopress plugin:

No scheduled milestone found for this plugin.

If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack.


Mu Wpcom plugin:

  • Next scheduled release: WordPress.com Simple releases happen semi-continuously (PCYsg-Jjm-p2)

If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack.


Wpcomsh plugin:

  • Next scheduled release: Atomic deploys happen twice daily on weekdays (p9o2xV-2EN-p2)

If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack.


Premium Analytics plugin:

No scheduled milestone found for this plugin.

If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack.

@github-actions github-actions Bot added the [Status] Needs Author Reply We need more details from you. This label will be auto-added until the PR meets all requirements. label Jun 19, 2026
retrofox added 2 commits June 19, 2026 15:23
Merge trunk's connect/syncing redirect guard into route.ts beforeLoad (was dropped when the route was replaced), then register the widgetModule entity.
Switch @wordpress/widget-{dashboard,primitives} from local link: to the npm 'next' dist-tag; drop the local Gutenberg docker mount. Host pieces (registry/endpoints/default-layout) stay.
@retrofox retrofox changed the title [DO NOT MERGE] Premium Analytics: dashboard on core Gutenberg packages via local symlinks Premium Analytics: dashboard on core Gutenberg packages (@next) Jun 19, 2026
retrofox and others added 3 commits June 19, 2026 16:11
The dashboard externalizes @wordpress/private-apis; only the Gutenberg plugin ships a private-apis whose opt-in allowlist includes @wordpress/widget-dashboard. Activate the plugin in the env.
Map the local Gutenberg checkout into the env for the private-apis runtime; packages stay on the npm 'next' tag.
Comment on lines +184 to +185
&& ! $gutenberg_active
&& version_compare( $GLOBALS['wp_version'] ?? '0', $force_threshold, '<' );

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If GB is active, but is an older version without the required package version support, this could break things.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could hardcode GB v22.6 check against GUTENBERG_VERSION when the threshold is set to 7.0? Since it's just a safeguard, hardcoding seems fine.

https://developer.wordpress.org/block-editor/contributors/versions-in-wordpress/

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, agreed.

We'll gate on GUTENBERG_VERSION (≥ 22.6 for the 7.0 threshold) so an older active Gutenberg still gets the superset polyfill instead of being skipped.

track @wordpress/private-apis @next so widget-dashboard opt-in resolves
@retrofox
retrofox marked this pull request as ready for review June 22, 2026 10:49
@retrofox
retrofox requested a review from a team as a code owner June 22, 2026 10:49
@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.

  • To test on WoA, go to the Plugins menu on a WoA dev site. Click on the "Upload" button and follow the upgrade flow to be able to upload, install, and activate the Jetpack Beta plugin. Once the plugin is active, go to Jetpack > Jetpack Beta, select your plugin (Jetpack or WordPress.com Site Helper), and enable the try/pa-core-packages-symlink branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack try/pa-core-packages-symlink
bin/jetpack-downloader test jetpack-mu-wpcom-plugin try/pa-core-packages-symlink

Interested in more tips and information?

  • In your local development environment, use the jetpack rsync command to sync your changes to a WoA dev blog.
  • Read more about our development workflow here: PCYsg-eg0-p2
  • Figure out when your changes will be shipped to customers here: PCYsg-eg5-p2

@jp-launch-control

jp-launch-control Bot commented Jun 22, 2026

Copy link
Copy Markdown

Code Coverage Summary

Coverage changed in 2 files.

File Coverage Δ% Δ Uncovered
projects/packages/premium-analytics/src/class-analytics.php 0/44 (0.00%) 0.00% 10 💔
projects/packages/wp-build-polyfills/src/class-wp-build-polyfills.php 90/99 (90.91%) 1.88% 0 💚

5 files are newly checked for coverage.

File Coverage
projects/packages/premium-analytics/src/class-widget-type-registry.php 0/63 (0.00%) 💔
projects/packages/premium-analytics/src/class-widget-type.php 0/8 (0.00%) 💔
projects/packages/premium-analytics/src/dashboard-layout.php 0/61 (0.00%) 💔
projects/packages/premium-analytics/src/widget-modules.php 0/35 (0.00%) 💔
projects/packages/premium-analytics/src/widget-types.php 0/21 (0.00%) 💔

Full summary · PHP report · JS report

If appropriate, add one of these labels to override the failing coverage check: Covered by non-unit tests Use to ignore the Code coverage requirement check when E2Es or other non-unit tests cover the code Coverage tests to be added later Use to ignore the Code coverage requirement check when tests will be added in a follow-up PR I don't care about code coverage for this PR Use this label to ignore the check for insufficient code coveage.

retrofox added 3 commits June 22, 2026 12:24
simplify isset ternary to null coalescing in dashboard-layout; suppress wp-build-generated jpa_get_registered_widget_modules in widget-types
declare jetpack-script-data + @wordpress/route deps; remove blank lines between import groups; complete hook and widget JSDoc
retrofox added 4 commits June 22, 2026 12:47
remove proxy-registry tarball: entries so the lockfile matches trunk/CI (npmjs registry omits them)
sync reference + description in the 6 dependent plugins after the polyfill changes
changelog entries for the 6 plugins whose composer.lock referenced wp-build-polyfills
@retrofox
retrofox requested review from a team as code owners June 22, 2026 12:55
@github-actions github-actions Bot added [Plugin] Backup A plugin that allows users to save every change and get back online quickly with one-click restores. [Plugin] Jetpack Issues about the Jetpack plugin. https://wordpress.org/plugins/jetpack/ [Plugin] mu wpcom jetpack-mu-wpcom plugin [Plugin] Social Issues about the Jetpack Social plugin [Plugin] VideoPress A standalone plugin to add high-quality VideoPress videos to your site. [Plugin] Wpcomsh labels Jun 22, 2026
retrofox and others added 2 commits June 22, 2026 14:52
reselect bumped to 5.2.0 via trunk; the 5.1.1 exclude is no longer installed
Comment thread projects/packages/wp-build-polyfills/src/class-wp-build-polyfills.php Outdated
@@ -0,0 +1,113 @@
<?php

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@retrofox do we need this because the packages we rely on are only front-end files, and this would only be available if we are on the latest GB or WP version?
Or is it expected for each plugin to create their own widget type?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have this file and several others because:

  1. They establish the foundation of the system's operational infrastructure, which powers the widget system and, in part, the dashboard.

  2. They haven't yet been published in Gutenberg/Core, as they are still tied to an experimental feature.

And no, the idea isn't for each plugin to set up its own system. Rather, as a purely temporary measure, we decided to create our own system in Premium Analytics.

We're talking about the most delicate piece of the entire implementation, mainly because it would be embedded within the WordPress core, which is no small matter.

louwie17
louwie17 previously approved these changes Jun 22, 2026

@louwie17 louwie17 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @retrofox & @nerrad for working on this, this tested well! I also checked some of the existing dashboards that rely on the polyfills.
The Premium Analytics dashboard also works great 👍

Code otherwise looks good, the dashboard stuff we can certainly iterate on.
I appreciate the addition of the GB and WP version checks per package 🥇

seed SCRIPT_FILENAME so wp_guess_url avoids an empty-needle warning on PHP < 8
@retrofox
retrofox merged commit 916d4ae into trunk Jun 22, 2026
94 of 96 checks passed
@retrofox
retrofox deleted the try/pa-core-packages-symlink branch June 22, 2026 17:57
Comment on lines +66 to +67
"@wordpress/widget-dashboard": "next",
"@wordpress/widget-primitives": "next",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is using "next" rather than an actual version number going to require lockfile updates every time a new "next" is tagged?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks and good feedback.

Short answer: no. pnpm pins the resolved snapshot (0.1.1-next.v.202606191442.0) in the lockfile, and CI's --frozen-lockfile only compares thenext specifier; it never re-hits the registry.

So a new next does not break CI or need a lockfile update.

The real trade-off is the opposite: the pin only moves on an explicit pnpm update, and any unrelated lockfile regen pulls whatever next points to at that moment, so we can get a surprise bump in a non-related diff.

These two are the experimental dashboard-widgets packages with no stable release yet, so next was the only tag.

We are pinning them to the exact version in Douglas's PR (#49838), the same place we scope the polyfill.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Short answer: no. pnpm pins the resolved snapshot (0.1.1-next.v.202606191442.0) in the lockfile, and CI's --frozen-lockfile only compares thenext specifier; it never re-hits the registry.

It seems your AI is unaware of the "Lock files are up to date" CI check. It looks like that would indeed start complaining as soon as a new "next" version is released.

We are pinning them to the exact version in Douglas's PR (#49838), the same place we scope the polyfill.

Good!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is using "next" rather than an actual version number going to require lockfile updates every time a new "next" is tagged?

It looks like that would indeed start complaining as soon as a new "next" version is released.

Good!

Thanks for answering the question. So setting the dependencies to a fixed tag will avoid this, right?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, using versions like 0.1.1-next.v.202606191442.0, as in #49838, will be fine.

@github-actions github-actions Bot added [Status] UI Changes Add this to PRs that change the UI so documentation can be updated. and removed [Status] Needs Author Reply We need more details from you. This label will be auto-added until the PR meets all requirements. [Status] In Progress labels Jun 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Docker Docs [Package] Premium Analytics [Package] Wp Build Polyfills [Plugin] Backup A plugin that allows users to save every change and get back online quickly with one-click restores. [Plugin] Jetpack Issues about the Jetpack plugin. https://wordpress.org/plugins/jetpack/ [Plugin] mu wpcom jetpack-mu-wpcom plugin [Plugin] Premium Analytics [Plugin] Social Issues about the Jetpack Social plugin [Plugin] VideoPress A standalone plugin to add high-quality VideoPress videos to your site. [Plugin] Wpcomsh [Status] UI Changes Add this to PRs that change the UI so documentation can be updated. [Tests] Includes Tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants