Configuration Reference
Purpose
This page centralizes ReactWP values that are read outside normal theme code: Node environment variables, generator arguments, WordPress constants, runtime filters, build budgets, and configuration precedence.
Environment variables are read when the corresponding Node process starts. WordPress constants should be defined in src/core/wp-config.php or injected by the hosting environment before the ReactWP runtime loads.
Static Generation
The static generator accepts environment variables and equivalent command-line arguments.
| Environment variable | CLI argument | Default | Meaning |
|---|---|---|---|
RWP_SITE_URL | --site | none, required | WordPress origin used for bootstrap and sitemap requests |
RWP_THEME | --theme | reactwp | theme slug used to resolve render input/output paths |
RWP_SSG_MAX_ROUTES | none | 5000 | maximum sitemap routes, clamped between 1 and 50000 |
RWP_SSG_MAX_JSON_BYTES | none | 10485760 | maximum API JSON response, clamped between 1 KiB and 50 MiB |
RWP_SSG_MAX_HTML_BYTES | none | 5242880 | maximum rendered fragment, clamped between 1 KiB and 20 MiB |
RWP_SSG_TIMEOUT | none | 15000 | request timeout in milliseconds, clamped between 1000 and 120000 |
RWP_SSG_ALLOW_EXTERNAL_OUTPUT | none | 0 | set to 1 only when a reviewed output path must leave the ReactWP project |
| none | --output | dist/wp-content/themes/<theme>/assets/render/static | static manifest and fragment destination |
| none | --renderer | dist/wp-content/themes/<theme>/assets/render/server.cjs | universal renderer bundle used during generation |
Examples:
$env:RWP_SITE_URL = 'https://example.com'
$env:RWP_THEME = 'my-theme'
npm run generate
npm run generate -- --site=https://example.com --theme=my-theme
Advanced output override:
npm run generate -- \
--site=https://example.com \
--theme=my-theme \
--renderer=../dist/wp-content/themes/my-theme/assets/render/server.cjs \
--output=../tmp/reactwp-static
RWP_SITE_URL is also read by npm run prod. When present, the production theme pipeline runs static generation after successful asset and render builds. When absent, SSG is skipped without failing production.
The WordPress site must be reachable from the build process, and its public ReactWP bootstrap and sitemap endpoints must return the routes to generate.
Local HTTPS Certificates
On Node versions that expose the system certificate APIs, the generator adds the operating system's trusted CA certificates to Node's normal CA list before making requests. A Laragon or development root certificate installed in Windows can therefore validate normally without disabling TLS security.
Test the endpoint independently when HTTPS still fails:
node --use-system-ca -e "fetch('https://example.test/wp-json/reactwp/v1/bootstrap').then(r => console.log(r.status))"
For an older Node version or a CA that is not installed in the operating system, point Node at the CA certificate explicitly:
$env:NODE_EXTRA_CA_CERTS = 'C:\path\to\development-root-ca.pem'
npm run generate -- --site=https://example.test
Do not use NODE_TLS_REJECT_UNAUTHORIZED=0. It disables certificate verification instead of trusting one known development authority.
Node SSR Service
npm run serve:ssr starts the built serve.mjs runtime. It reads:
| Variable | Default | Unit | Meaning |
|---|---|---|---|
RWP_RENDER_BUNDLE | sibling server.cjs | path | alternate universal renderer bundle |
RWP_SSR_HOST | 127.0.0.1 | host | interface used by the Node HTTP server |
RWP_SSR_PORT | 3100 | port | listening port |
RWP_SSR_SECRET | empty | string | shared render-request secret |
RWP_SSR_BODY_LIMIT | 5242880 | bytes | maximum JSON request body |
RWP_SSR_RESPONSE_LIMIT | 5242880 | bytes | maximum JSON response body; the rendered HTML is checked before it is returned |
RWP_SSR_TIMEOUT | 8000 | milliseconds | maximum duration of one Node render |
RWP_SSR_CONCURRENCY | 8 | requests | maximum simultaneous renders |
RWP_SSR_ALLOW_INSECURE_LOOPBACK | 0 | boolean | 1 permits secretless loopback only when WordPress also explicitly permits local/development insecure loopback |
The service exposes:
GET /health
POST /render
GET /health returns ok, the active render count, and the configured concurrency. Responses from the render service use Cache-Control: no-store because WordPress, not Node, owns HTML cache policy.
The Node service requires an RWP_SSR_SECRET of at least 32 characters on loopback and remote hosts. The only exception is an explicit local-development opt-in: the Node process must set RWP_SSR_ALLOW_INSECURE_LOOPBACK=1, WordPress must run as local or development, and rwp_ssr_allow_insecure_loopback must return true. Never use that exception in production.
Example process configuration:
$env:RWP_SSR_HOST = '127.0.0.1'
$env:RWP_SSR_PORT = '3100'
$env:RWP_SSR_SECRET = 'replace-with-a-long-random-value'
$env:RWP_SSR_CONCURRENCY = '8'
npm run serve:ssr
WordPress SSR Connection
Configure WordPress with:
define('RWP_SSR_ENDPOINT', 'http://127.0.0.1:3100/render');
define('RWP_SSR_SECRET', getenv('RWP_SSR_SECRET'));
| Constant | Default | Meaning |
|---|---|---|
RWP_SSR_ENDPOINT | empty | complete Node /render URL; an empty value disables runtime SSR and static regeneration |
RWP_SSR_SECRET | environment fallback | value sent in X-ReactWP-Render-Secret |
The WordPress secret and Node secret must match. Never commit a production secret directly to the repository.
WordPress accepts loopback renderer URLs by default. A remote renderer must use HTTPS and explicitly opt in through rwp_ssr_allow_remote_endpoint.
WordPress Render Filters
These filters control PHP-to-Node behavior:
| Filter | Default | Unit | Purpose |
|---|---|---|---|
rwp_ssr_endpoint | RWP_SSR_ENDPOINT | URL | override the render endpoint |
rwp_ssr_timeout | 2.5 | seconds | WordPress HTTP request timeout |
rwp_ssr_circuit_seconds | 20 | seconds | temporary fallback period after a renderer failure |
rwp_ssr_max_html_bytes | 5242880 | bytes | largest accepted SSR HTML response |
rwp_ssr_allow_remote_endpoint | false | boolean | allow a non-loopback HTTPS renderer |
rwp_ssr_allow_insecure_loopback | false | boolean | allow secretless loopback only for local/development WordPress when Node also opts in |
rwp_ssr_payload | current payload | array | add request-specific render data |
rwp_ssr_cache_identity | current user ID for authenticated private requests | string | partition private SSR cache entries |
rwp_ssr_cache_query_keys | [] | keys | exact query keys that may participate in cached SSR identities |
rwp_ssr_cache_max_query_bytes | 2048 | bytes | maximum normalized query string considered for SSR caching |
rwp_static_render_max_html_bytes | 5242880 | bytes | largest static fragment WordPress will read |
rwp_static_regeneration_batch_size | 10 | routes | routes processed by one regeneration cron event |
rwp_static_render_manifest_paths | runtime and theme manifests | paths | replace or extend static manifest lookup |
rwp_initial_render_enabled | true | boolean | globally enable static/SSR initial HTML |
rwp_prerender_skip_loader | true | boolean | skip the initial loader for valid pre-rendered HTML |
The Node timeout and WordPress timeout are separate. By default, WordPress stops waiting after 2.5 seconds even though Node allows a render to run for up to 8 seconds. Increase both deliberately when a project truly needs longer renders; first investigate slow payload construction or template work.
Bundle Budgets
Production bundle reporting reads:
| Variable | Default | Meaning |
|---|---|---|
RWP_MAX_JS_ASSET_KB | 250 | raw warning limit for one JavaScript asset |
RWP_MAX_INITIAL_GZIP_KB | 170 | gzip warning limit for the complete initial JavaScript entry |
RWP_BUNDLE_BUDGET_STRICT | 0 | set to 1 to turn budget warnings into build failures |
$env:RWP_MAX_JS_ASSET_KB = '220'
$env:RWP_MAX_INITIAL_GZIP_KB = '150'
$env:RWP_BUNDLE_BUDGET_STRICT = '1'
npm run prod
A production bundle containing React's development JSX runtime fails regardless of budget strictness.
Core Download Variables
npm run get:core reads:
| Variable | Default | Meaning |
|---|---|---|
REACTWP_WORDPRESS_URL | official WordPress ZIP | alternate WordPress archive |
REACTWP_WORDPRESS_SHA256 | empty for the official source | required SHA-256 for a custom WordPress archive |
REACTWP_WORDPRESS_LOCALE | en_US | locale used for official WordPress checksum verification |
REACTWP_ACF_EDITION | interactive choice; free outside a TTY | free, pro, or none |
REACTWP_ACF_LICENSE_KEY | empty | ACF PRO license supplied as the official Composer username |
REACTWP_ACF_SITE_URL | RWP_SITE_URL, then empty | complete licensed site URL supplied as the Composer password |
REACTWP_ACF_VERSION | latest | optional exact ACF Free or PRO version |
REACTWP_ACF_COMPOSER_REPOSITORY | official ACF repository | compatible PRO Composer repository override |
REACTWP_ACF_URL | empty | reviewed private ACF PRO ZIP override |
REACTWP_ACF_SHA256 | empty | required SHA-256 for a private PRO archive |
REACTWP_DOWNLOAD_HOSTS | official WordPress hosts | comma-separated additional hosts for custom archives or repositories |
REACTWP_COMPOSER_BINARY | composer | alternate Composer executable or command |
REACTWP_PHP_BINARY | detected PHP/Laragon PHP | PHP executable made available to Composer |
REACTWP_SKIP_ACF | 0 | legacy 1 alias for edition none |
These variables affect source preparation, not the browser runtime. PRO credentials are passed only to the temporary Composer child process and are not written into dist, Composer files, or project configuration.
Optional First-Load Scaffold
The PHP starter scaffold is controlled separately from build environment variables:
define('RWP_FIRSTLOAD', true);
The default is false. It can be enabled before or after WordPress installation. When enabled, an administrator request can seed the missing home page, permalink structure, language rows, primary menu location, and starter menu. ACF repeaters stored as 0 are considered empty, and missing ACF field references are repaired without replacing populated rows. ReactWP records the successful scaffold schema version in rwp_firstload and serializes execution with rwp_firstload_lock.
Projects can calculate the opt-in through PHP with rwp_firstload_enabled, but should keep the default disabled in reusable packages:
add_filter('rwp_firstload_enabled', function($enabled){
return $enabled;
});
The default schema version is 1. A project that adds an idempotent first-load migration can request a later run by increasing the version:
add_filter('rwp_firstload_version', function(){
return 2;
});
The completion option is updated only after the home page, language repeater, and theme-location repeater are ready. Incrementing this version is not a replacement for a general database migration system.
Remove the constant after setup. Do not treat this scaffold as a migration, fixture, or content synchronization system.
Render Configuration Precedence
ReactWP resolves render configuration from general defaults to route-specific overrides:
- JavaScript template registry metadata written to
templates.json - PHP
rwp_render_templatesvalues for the template name - render values already present on the route
- the queried object's React Rendering ACF fields
rwp_render_configrwp_render_modefor the final mode only
Later values override earlier values. Cache objects are merged by property, but a later cache.tags array replaces the earlier custom tag array while PHP resolves the route. During universal rendering, ReactWP unions the JavaScript registry tags with the final route tags, then adds baseline tags such as render:all, menu:all, settings:all, and template:<name>.
Use the JavaScript registry for project defaults, ACF for editor-controlled per-route choices, and final PHP filters only when the decision requires server context.
Cache Scope Defaults
Normalized defaults depend on render mode:
| Setting | client | static | server |
|---|---|---|---|
cache.html | false | true | false |
cache.scope | public | public | private |
cache.ttl | 0 | 0 | 0 |
cache.payload | true | true | true |
cache.media | true | true | true |
cache.tags | []; no HTML entry | [] plus baseline render tags | [] plus baseline render tags when rendered |
For SSR, HTML caching needs both cache.html: true and a positive cache.ttl. Public SSR cache is bypassed for logged-in users. Private anonymous cache is disabled unless rwp_ssr_cache_identity returns a project-controlled identity.
Configuration Safety
- Keep renderer secrets outside source control.
- Prefer loopback communication between PHP and Node.
- Do not expose the render service directly as a public frontend endpoint.
- Keep private output private or uncached; never use one shared identity for unrelated sessions.
- Treat remote renderer opt-in as a deployment-security decision, not a convenience flag.
- Verify units: Node render timeout is milliseconds, WordPress HTTP timeout is seconds, and body/HTML limits are bytes.
Continue with Client, Static, and Server Rendering, Cache Tags, Build Commands, and Hooks and Filters.