Content and Menus
Content Modeling
ReactWP expects WordPress and ACF to define the content model.
WordPress provides:
- pages
- posts
- taxonomies
- menus
ACF provides:
- structured route data
- site settings
- theme-level configuration fields
Menu Locations
Menu locations are driven by the ReactWP site settings rather than being forced directly in the theme.
That means the starter can ship a default menu location while still allowing the project owner to rename or remove locations from the admin.
The runtime reads those locations from the Site settings options page and registers them with WordPress automatically.
The location slug becomes part of the frontend contract, because React templates consume menus through keys such as navigation.primary.
Default Starter Data
On first boot, ReactWP seeds:
- a starter home page
- default language rows
- starter menu location rows
- a starter navigation menu assigned to the default location
By default, the first boot creates a primary location and assigns a starter menu to it.
That starter row is not hardcoded forever. It is just seeded as a default and can be removed or renamed later from Site settings.
How To Add A Menu Location
ReactWP expects menu locations to be created from the admin, not hardcoded in the theme.
Typical flow:
- Open
ReactWP -> Site settings - Find the
Theme Locationsrepeater - Add a new row
- Set a
slug - Fill the translated names such as
name_frandname_en - Save the settings page
After that, ReactWP registers the new location with WordPress.
How To Assign A Menu To That Location
Once the location exists:
- Open
Appearance -> Menus - Create or edit a WordPress menu
- Assign it to the location you created
- Save the menu
ReactWP will then expose that location in the frontend bootstrap payload.
Frontend Navigation Shape
Menus are normalized by the PHP runtime before they reach React.
The frontend receives navigation data through the bootstrap payload, so templates and components can consume navigation without rebuilding raw WordPress menu structures.
Each location becomes an array of normalized items.
Each item can include:
idlabeltitleurlpathtargetclasseschildren
The children value is already normalized as a tree, so dropdown or nested menu rendering does not need to rebuild parent-child relationships manually in React.
How To Use A Menu In A Template
Templates receive navigation as a prop from the React app shell.
Example:
const ExampleTemplate = ({ navigation }) => {
const primaryMenu = navigation.primary || [];
return (
<nav className="site-nav">
{primaryMenu.map((item) => (
<a key={item.id} href={item.url}>
{item.label}
</a>
))}
</nav>
);
};
For React navigation and prefetching, use AppLink or Button instead of a raw anchor:
import AppLink from '../components/AppLink';
const ExampleTemplate = ({ navigation }) => {
const primaryMenu = navigation.primary || [];
return (
<nav className="site-nav">
{primaryMenu.map((item) => (
<AppLink key={item.id} to={item.path}>
{item.label}
</AppLink>
))}
</nav>
);
};
How To Use A Menu In The Header
The header is not rendered as a page template.
It is a shell-level component mounted by AppShell, so it does not receive navigation automatically the same way a page template does.
If you want a header menu, pass navigation through headerProps from App.jsx.
Example:
import { runtime } from './inc/Runtime';
<AppShell
showHeader={true}
headerProps={{
className: 'site-header',
navigation: runtime.navigation,
site: runtime.site,
theme: runtime.theme,
system: runtime.system
}}
showFooter={false}
>
<Outlet />
</AppShell>
Then your header component can pass that data to a dedicated navigation component:
const Header = ({ navigation = {}, ...props }) => {
const primaryMenu = navigation.primary || [];
return (
<header {...props}>
<nav>
{primaryMenu.map((item) => (
<AppLink key={item.id} to={item.path}>
{item.label}
</AppLink>
))}
</nav>
</header>
);
};
This is the recommended pattern because:
- page templates already receive
navigationautomatically - shell components like
Headerdo not App.jsxis the correct place to distribute shared shell props
If you import runtime.navigation directly inside Header.jsx, that also works, but passing it through headerProps is clearer and easier to follow.
Nested Menus
Menu items are already normalized as a tree.
That means child items live in item.children, so nested rendering can be handled recursively if the project needs dropdowns or multi-level navigation.
Where This Data Comes From
Menu normalization happens in the PHP runtime, mainly through:
inc/runtime/MenuBuilder.phpinc/runtime/Bootstrap.php
That is why frontend code can work with navigation.primary directly instead of reconstructing raw wp_get_nav_menu_items() data.