Skip to main content

Use ReactWP Headless

ReactWP can serve normalized WordPress data to a separate frontend without requiring the integrated React theme runtime. The external application owns its rendering, routing, assets, and deployment.

Set the WordPress URL

Store the WordPress origin in the external frontend's environment configuration:

WORDPRESS_URL=https://cms.example.com

Use HTTPS in production.

Allow the Frontend Origin

In WordPress, open Site settings > Headless API and add the exact external origin under Allowed Headless Origins:

https://www.example.com
http://localhost:3000

Include the scheme and port. ReactWP does not use a wildcard origin for credentialed requests.

Origins can also be added in PHP:

add_filter('rwp_headless_allowed_origins', function($origins){
$origins[] = 'https://www.example.com';

return $origins;
});

Read the Bootstrap Payload

The bootstrap endpoint returns shared site, theme, system, navigation, SEO, and initial route data:

const response = await fetch(
`${process.env.WORDPRESS_URL}/wp-json/reactwp/v1/bootstrap`
);

if (!response.ok) {
throw new Error(`ReactWP bootstrap failed: ${response.status}`);
}

const bootstrap = await response.json();

Public responses include apiVersion and generatedAt so the frontend can validate and observe the contract.

The bootstrap exposes site.language and the complete WordPress site.locale. For a translated bootstrap, pass the requested language and localized view:

const url = new URL('/wp-json/reactwp/v1/bootstrap', process.env.WORDPRESS_URL);
url.searchParams.set('lang', 'fr');
url.searchParams.set('view', '/fr/');

const bootstrap = await fetch(url).then((response) => response.json());

User identity is deliberately separate from this cacheable response. Fetch /wp-json/reactwp/v1/auth/me with credentials: 'include' when the frontend needs the current WordPress user.

Resolve a Route

Request any public WordPress permalink through the route endpoint. The view parameter is required:

async function getRoute(pathname) {
const url = new URL('/wp-json/reactwp/v1/route', process.env.WORDPRESS_URL);
url.searchParams.set('view', pathname);

const response = await fetch(url);

if (!response.ok) {
throw new Error(`ReactWP route failed: ${response.status}`);
}

const payload = await response.json();
return payload.route;
}

const about = await getRoute('/about/');

The normalized route includes its path, status, type, template, title, data, SEO, media groups, head entries, and related endpoint links.

Use route.lang for the language of the resolved route and retain the bootstrap language only as a fallback:

const language = about.lang || bootstrap.site.language || 'en';
const locale = bootstrap.site.locale || 'en_US';

For multilingual routes, pass the localized WordPress permalink as view, for example /fr/a-propos/. Bootstrap, navigation, settings, sitemap, and preview requests also accept ?lang=fr when the external frontend needs WordPress to switch language before building the response.

Do not consume the integrated theme's inline #reactwp-bootstrap script from an external application. The public endpoints pass through the stable, sanitized headless contract.

Read Navigation

Fetch every menu location:

const response = await fetch(
`${process.env.WORDPRESS_URL}/wp-json/reactwp/v1/navigation`
);

const payload = await response.json();

Or request one location:

GET /wp-json/reactwp/v1/navigation?location=primary

Authentication and Previews

Public content requests do not require a WordPress session and never expose drafts, private posts, scheduled posts, trashed posts, or password-protected posts. Authenticated browser requests use WordPress cookies, a REST nonce, credentials: 'include', and an allowlisted origin.

ReactWP also provides signed preview payloads so unpublished content does not need to become public.

Continue with the Headless API Reference for endpoints, response fields, login, logout, current users, previews, public settings, sitemap customization, and caching.

Production Responsibility

ReactWP controls the WordPress API and the ReactWP cache generation. The external application controls its own HTML rendering, framework cache, revalidation, assets, and hosting.

When content changes, use ReactWP's cache generation or invalidation hooks to tell the external deployment when cached data must be refreshed. See Cache and Revalidation.