Create a new screen in the Multi-site Dashboard with automatic route registration
Creates new screens in client/dashboard with automatic route discovery and registration.
First, find all router files and extract available routes.
Use Glob to discover router files:
client/dashboard/app/router/*.tsx
client/dashboard/app/router/*.ts
For each router file, use Grep to extract route information.
Find exported route constants:
export\s+const\s+(\w+Route)\s*=\s*createRoute
Extract parent relationships:
getParentRoute:\s*\(\)\s*=>\s*(\w+Route)
Extract path segments:
path:\s*['"]([^'"]+)['"]
Extract component import paths:
import\(\s*['"]([^'"]+)['"]\s*\)
For each discovered route, record:
siteBackupsRoute)siteRoute)'backups')Menu discovery happens after the user selects a parent route. Find menus relative to the route's location.
Based on the selected parent route's import path, determine where to search for menus:
Extract the component directory from the parent route's lazy import
import('../../sites/backups') → search in client/dashboard/sites/import('../../me/profile') → search in client/dashboard/me/Use Glob to find menu files in that area:
client/dashboard/{area}/**/*-menu/index.tsx
Also check the app-level menu for top-level routes:
client/dashboard/app/*-menu/index.tsx
For each discovered menu file, use Grep to find:
Existing menu items pattern:
<ResponsiveMenu\.Item\s+to=
Route references in menu:
to=\{?\s*[`'"/]([^`'"}\s]+)
This helps understand the menu's structure and where to add new items.
Menu items use ResponsiveMenu.Item:
<ResponsiveMenu.Item to="/path/to/screen">
{ __( 'Menu Label' ) }
</ResponsiveMenu.Item>
Conditional menu items check feature support:
{ siteTypeSupports.featureName && (
<ResponsiveMenu.Item to={ `/sites/${ siteSlug }/feature` }>
{ __( 'Feature' ) }
</ResponsiveMenu.Item>
) }
Ask the user for the following using AskUserQuestion:
custom-settings)custom-settings)Custom settings)Based on the selected parent route's import path, determine where to create the component.
Pattern: If parent imports from ../../sites/backups, new screen goes in client/dashboard/sites/{screen-name}/
For sites area: client/dashboard/sites/{screen-name}/index.tsx
For me area: client/dashboard/me/{screen-name}/index.tsx
For other areas: Follow the same pattern from parent's import path
Generate a basic component with the standard layout.
import { __ } from '@wordpress/i18n';
import { PageHeader } from '../../components/page-header';
import PageLayout from '../../components/page-layout';
export default function {ComponentName}() {
return (
<PageLayout
header={
<PageHeader
title={ __( '{PageTitle}' ) }
description={ __( '{PageDescription}' ) }
/>
}
>
{/* Content goes here */}
</PageLayout>
);
}
Add the route definition to the same router file as the parent route.
Add after other route exports in the file:
export const {routeName}Route = createRoute( {
head: () => ( {
meta: [
{
title: __( '{PageTitle}' ),
},
],
} ),
getParentRoute: () => {parentRoute},
path: '{routePath}',
} ).lazy( () =>
import( '{componentImportPath}' ).then( ( d ) =>
createLazyRoute( '{routeId}' )( {
component: d.default,
} )
)
);
Find where the parent route is used in the create*Routes() function and add the new route.
For standalone routes (direct child of main area route):
// Find the routes array (e.g., siteRoutes, meRoutes)
// Add the new route to the array
siteRoutes.push( newScreenRoute );
For nested routes (child of a feature route):
// Find where parent uses .addChildren()
// Add the new route to the children array
parentRoute.addChildren( [ existingRoute, newScreenRoute ] )
If the user requested a navigation menu entry, add it to the discovered menu file.
Use the menu discovered in Step 2 based on the route's area:
sites, me, plugins)client/dashboard/{area}/**/*-menu/index.tsxclient/dashboard/app/primary-menu/index.tsxRead the target menu file and find an appropriate location (typically before the closing </ResponsiveMenu> tag).
Build the route path from parent route's path + new screen path:
/sites/$siteSlug and screen path is analytics → /sites/${ siteSlug }/analytics/me and screen path is api-keys → /me/api-keysInsert menu item:
<ResponsiveMenu.Item to={ `{fullRoutePath}` }>
{ __( '{PageTitle}' ) }
</ResponsiveMenu.Item>
Analyze the existing menu items to match the pattern:
siteSlug, use the same patternIf the screen requires feature gating (check if similar items in the menu use conditions):
{ siteTypeSupports.{featureName} && (
<ResponsiveMenu.Item to={ `/sites/${ siteSlug }/{routePath}` }>
{ __( '{PageTitle}' ) }
</ResponsiveMenu.Item>
) }
Follow the coding standards documented in client/dashboard/docs/.