Goal
Modernize Jetpack's Newsletter product into a single, unified wp-admin destination with two tabs:
- Subscribers (default) — the DataViews-based subscribers UI shipped in #48386.
- Settings — every setting from the existing
projects/packages/newsletter/ settings screen, ported onto the new chassis.
After this work the standalone "Subscribers" wp-admin entry goes away. There is one menu item: Newsletter.
This umbrella supersedes the prototype umbrella (#48416) and PR (#48420). The prototype is the working reference; this umbrella is the shipping plan.
Approach
Six small, self-contained PRs. Each builds on the previous one. Everything from PR 1 onward is gated behind a feature filter (rsm_jetpack_ui_modernization_newsletter) — the legacy Newsletter Settings page renders unchanged unless a site explicitly opts in. The final PR flips the default and retires the legacy surface.
This mirrors the cadence of the VideoPress wp-build scaffold (#48494).
PRs
Test plan (per PR)
- Hard-reload
wp-admin/admin.php?page=jetpack-newsletter with the filter OFF — legacy Newsletter Settings page is unchanged at every step.
- Add
add_filter( 'rsm_jetpack_ui_modernization_newsletter', '__return_true' ); and reload — the new chassis renders, growing in capability PR-by-PR.
- Toggle the filter back off — legacy returns immediately, no cache clears.
- PR 6 removes the gate entirely and the legacy surface; the test plan there is the smoke test for the unified product.
Architecture decisions (carried from #48416)
- Where it lives. The unified product lives in
projects/packages/newsletter/. The package keeps its name and menu slug (jetpack-newsletter).
- Scaffolding source of truth. wp-build pipeline (alongside webpack until PR 6);
Page from @wordpress/admin-ui; @wordpress/route for tabs; React Query; WP_Build_Polyfills; the boot-layout stage / inspector pattern.
- Tabs.
Tabs from @wordpress/ui, route-driven via ?tab=, persistent Tabs.Root so the indicator slides.
- Settings keeps its 9 sections 1:1. The card primitive moves to WPDS
Card.* from @wordpress/ui. Structural cleanup is a follow-up.
- Menu changes. Standalone Subscribers menu retires. Newsletter is the single entry.
- Filter compatibility.
jetpack_wp_admin_subscriber_management_enabled continues to gate the in-admin Subscribers experience inside the Newsletter page.
- Backend. REST proxies (
/wpcom/v2/subscribers/*) and the existing Newsletter settings REST API are preserved as-is.
Out of scope
- Restructuring the 9 settings sections.
- Adding new settings, new Subscribers features, or migrating REST proxies.
- Touching the Newsletter block or any editor-side code.
References
- Prototype umbrella (superseded): #48416
- Prototype PR (superseded, kept as working reference): #48420
- VideoPress wp-build scaffold (PR 1 cadence model): #48494
- Subscribers DataViews port: #48386
- Forms tabs reference:
projects/packages/forms/src/dashboard/components/forms-responses-tabs/index.tsx
- WPDS
Card / Tabs: @wordpress/ui
Goal
Modernize Jetpack's Newsletter product into a single, unified wp-admin destination with two tabs:
projects/packages/newsletter/settings screen, ported onto the new chassis.After this work the standalone "Subscribers" wp-admin entry goes away. There is one menu item: Newsletter.
This umbrella supersedes the prototype umbrella (#48416) and PR (#48420). The prototype is the working reference; this umbrella is the shipping plan.
Approach
Six small, self-contained PRs. Each builds on the previous one. Everything from PR 1 onward is gated behind a feature filter (
rsm_jetpack_ui_modernization_newsletter) — the legacy Newsletter Settings page renders unchanged unless a site explicitly opts in. The final PR flips the default and retires the legacy surface.This mirrors the cadence of the VideoPress wp-build scaffold (#48494).
PRs
<h1>Newsletter</h1>. No tabs, no Subscribers, no Settings move.@wordpress/routeshell behind flag. #48574 — Replace the placeholder withPagefrom@wordpress/admin-ui+QueryClientProvider, lift analytics init from the legacy app to the Stage, add an empty Inspector slot, gate the inspector hook on asubscriber/uURL param. Tabs and actual Subscribers/Settings content land in PR 3 / PR 4._inc/subscribers/(porting from the prototype branch). LiftGravatarinto@automattic/jetpack-components/gravatar. Single route, no tab UI yet./route with?tab=drivingTabs.Rootfrom@wordpress/ui; persistent tabs so the active-tab indicator slides. Mount the existing 9 settings sections inside the Settings tab unchanged (legacy primitives). Page chrome polish: sticky header, opaque background, full-width tab-row separator.Card.Root/Card.Header/Card.Title/Card.Contentfrom@wordpress/ui.ExternalLink→ WPDSLink openInNewTab; legacyButtonsave buttons opt into__next40pxDefaultSize. Pure refactor inside the flagged chassis.true(or remove the gate entirely). Retire the standalone Subscribers wp-admin menu and the "Subscribers ↗" Calypso shortcut. Remove thesubscribers-dashboardpackage. Addjetpack_newsletter_tab_viewTracks event; lift analytics init to the page Stage; ARIA Tabs verified; RTL pass.Test plan (per PR)
wp-admin/admin.php?page=jetpack-newsletterwith the filter OFF — legacy Newsletter Settings page is unchanged at every step.add_filter( 'rsm_jetpack_ui_modernization_newsletter', '__return_true' );and reload — the new chassis renders, growing in capability PR-by-PR.Architecture decisions (carried from #48416)
projects/packages/newsletter/. The package keeps its name and menu slug (jetpack-newsletter).Pagefrom@wordpress/admin-ui;@wordpress/routefor tabs; React Query;WP_Build_Polyfills; the boot-layout stage / inspector pattern.Tabsfrom@wordpress/ui, route-driven via?tab=, persistentTabs.Rootso the indicator slides.Card.*from@wordpress/ui. Structural cleanup is a follow-up.jetpack_wp_admin_subscriber_management_enabledcontinues to gate the in-admin Subscribers experience inside the Newsletter page./wpcom/v2/subscribers/*) and the existing Newsletter settings REST API are preserved as-is.Out of scope
References
projects/packages/forms/src/dashboard/components/forms-responses-tabs/index.tsxCard/Tabs:@wordpress/ui