Skip to content

Dashboard: add A4A entrypoint and routing#109357

Draft
yashwin wants to merge 1 commit intotrunkfrom
dashboard-a4a
Draft

Dashboard: add A4A entrypoint and routing#109357
yashwin wants to merge 1 commit intotrunkfrom
dashboard-a4a

Conversation

@yashwin
Copy link
Copy Markdown
Contributor

@yashwin yashwin commented Mar 18, 2026

Proposed Changes

  • Add an A4A Dashboard entrypoint (entry-dashboard-a4a) with its own hostname (my.a4a.localhost) and A4A-specific routes.
  • Register A4A server routing (including non-section routes like /overview and /client/subscriptions) so direct hits/refresh work.
  • Add A4A agency/client surfaces and menu wiring, plus a context provider to ensure /agency is fetched and cached.

Why are these changes being made?

  • Enable local development of the A4A-flavored Dashboard and ensure it behaves correctly on both /a4a and my.a4a.localhost.

Testing Instructions

Note: You should have an A4A account: https://agencies.automattic.com/signup

  • Run yarn start-dashboard.
  • Visit http://my.a4a.localhost:3000/.
    • Verify you are redirected to the public API for authorization.
  • Navigate to /overview and hard-refresh; confirm it still loads (no "Cannot GET /overview").
  • Navigate to /client/subscriptions and hard-refresh; confirm it still loads.

Pre-merge Checklist

  • Has the general commit checklist been followed? (PCYsg-hS-p2)
  • Have you written new tests for your changes?
  • Have you tested the feature in Simple, Atomic, and self-hosted Jetpack sites?
  • Have you checked for TypeScript, React or other console errors?
  • Have you tested accessibility for your changes? Ensure the feature remains usable with various user agents (e.g., browsers), interfaces (e.g., keyboard navigation), and assistive technologies (e.g., screen readers).
  • Have you used memoizing on expensive computations? More info in Memoizing with create-selector and Using memoizing selectors and Our Approach to Data
  • Have you added the "[Status] String Freeze" label as soon as any new strings were ready for translation.
  • For changes affecting Jetpack: added "[Status] Needs Privacy Updates" label if needed.

Made with Cursor

Enable the A4A dashboard entrypoint in dashboard development with hostname support, server routes, and agency/client surfaces.

Made-with: Cursor
@yashwin yashwin self-assigned this Mar 18, 2026
@matticbot
Copy link
Copy Markdown
Contributor

This PR modifies the release build for the following Calypso Apps:

For info about this notification, see here: PCYsg-OT6-p2

  • notifications
  • odyssey-stats

To test WordPress.com changes, run install-plugin.sh $pluginSlug dashboard-a4a on your sandbox.

Copy link
Copy Markdown
Member

@p-jackson p-jackson left a comment

Choose a reason for hiding this comment

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

Nice, it's a good start! Looks like you've found the main places where configuration happens. My main encouragement is to use things like if ( appConfig.name === 'A4A' ) {} very sparingly and to try and think about how a different product based on subscriptions (think JP cloud) might also use the features you're creating.

Something that hasn't been modified in this PR yet (which is fine) is the site overview page (/sites/$siteSlug). That is the one place where we do have a lot of "if dotcom" and "if ciab" logic since they each want different cards. Bringing A4A into the MSD could be the opportunity to change this a bit. Have 3 separate overview page components

  • <DotComSiteOverview>
  • <CiabSiteOverview>
  • <PressableSiteOverview>
    Which all compose themselves out of the same grid component building blocks for consistency, but have freedom about which cards they want to show.

Anyway, just pondering.

<p>
{ __(
'Minimal placeholder for the A4A agency client subscriptions overview.',
'full-site-editing'
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.

Just wondering here whether you would expect the a4a strings to exist in a different translation domain from the rest of MSD?

* Temporary location.
*
* This is dashboard-local while A4A routing/entrypoints/auth are still evolving.
* Once stabilized, we should move the query builder into `@automattic/api-queries`
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.

I think you should feel confident putting your queries into the package even while they're still stabilising. The package isn't published to npm, and we've been freely tweaking the queries in that package as we go.

The reason I'd prefer the queries in their is that this would introduce a new data/ folder and I worry it would being to be used in ways that we don't want.

* We use the standard dashboard auth flow (`wpcom_token`) rather than the legacy
* A4A-specific token (`wpcom_token_a4a`) to avoid OAuth loops in dashboard environments.
*/
export async function wpcomA4ARequest< T >(
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.

Is there something special about these types of requests that mean they can't be in @automattic/api-core? lib/wp is where we change the request logic based on whether we are using cookies or oauth, perhaps any special tokens related to a4a would belong in lib/wp rather than here?


export const A4A_CONTEXT_QUERY_KEY = [ 'a4a', 'agency-context' ] as const;

export function useA4AContextQuery( enabled: boolean ) {
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.

A couple points about this request hook.

It might be worth taking a look at

to see how we're using request objects instead of hooks throughout MSD. We've found that request objects scale much better, since sometimes you want useQuery, sometimes useSuspenseQuery, sometimes ensureQueryData, etc. etc. And that those decisions are best left up to the call site.

The other is that I worry about a request specifically called "a4a context". We've tried to prevent so much branching logic throughout the code by removing things like "if ciab", "if dotcom", etc. and I worry that something called "a4a context" would result in that sort of branching within the product. Is the data truly only applicable to A4A? Things like is_client_user and has_agency seem like they're related to the logged in user and so would it make sense to incorporate these things into the user data?


export default function AgencyMenu() {
const { user } = useAuth();
const { data: a4aContext } = useA4AContextQuery( Boolean( user ) );
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.

This the sort of place where we would use useSuspenseQuery, since rendering can't continue until the data has finished loading.

import { useAuth } from './auth';
import { useAppContext } from './context';

export default function A4AContextProvider( { children }: { children: React.ReactNode } ) {
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.

I'm not sure what exactly this A4AContextProvider is providing 🤔

Logo: React.FC | null;
LoadingLogo?: React.FC;
supports: {
agency: boolean;
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.

I'm not sure whether we should have two booleans here, one for agency overview and one for the client subscription page 🤔 I see how they sort of go together, but we've also always had a 1:1 match of these AppConfig flags per menu item.

- Shared core functionality

Currently, the dashboard supports two main entry points:
Currently, the dashboard supports multiple entry points:
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.

Suggested change
Currently, the dashboard supports multiple entry points:
The dashboard supports multiple entry points:

@p-jackson
Copy link
Copy Markdown
Member

This might be a conversation for another PR, but @yashwin if you take a look at https://github.com/Automattic/wp-calypso/blob/60207285a9ac5ba14df20897c1a3267db2131197/client/dashboard/utils/site-type-feature-support.ts#L35 you see that each site supports different features.

Do you think that A4A is likely to be a "site type" according to getSiteTypeFeatureSupports? Or do you see it more as dotcom and pressable are the site types?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants