Skip to main content

Templates

The template registry connects WordPress route names to lazy React components. Most projects only need to register templates in one configuration file.

Role

The template registry maps WordPress route template names to lazy React components.

It gives the runtime a single place to resolve:

  • which React template should render a route
  • how that template should be lazy-loaded
  • whether its initial HTML is client-rendered, static, or server-rendered
  • which dependencies invalidate its HTML fragment
  • how a project can override or add templates safely

Main Files

  • src/themes/reactwp/js/inc/TemplateRegistry.js
  • src/themes/reactwp/js/inc/config/configureTemplateRegistry.js
  • src/themes/reactwp/js/inc/initializeTemplateRegistry.js

Defaults

ReactWP registers these templates automatically:

  • Default
  • NotFound

Projects can then override those entries or add new ones.

Registered templates are rendered by the frontend runtime with the standard template props:

  • route
  • site
  • theme
  • system
  • navigation
  • currentUser

Each registered entry is normalized into an object that contains:

  • Component
  • preload()
  • load()
  • render
  • cache
  • assetKey

That is why the loader can preload a template chunk before the route is revealed.

Customization

Use config/configureTemplateRegistry.js for project-level registration.

Example:

import { registerTemplate } from '../TemplateRegistry';

export const configureTemplateRegistry = () => {
registerTemplate('SingleService', () => import('../../templates/SingleService'));
registerTemplate('Archive', () => import('../../templates/Archive'));
};

The import path is relative to the config file, not to TemplateRegistry.js.

You can also override an existing template name:

import { registerTemplate } from '../TemplateRegistry';

export const configureTemplateRegistry = () => {
registerTemplate('Default', () => import('../../templates/MyCustomDefault'));
};

The registry resets its safe defaults before project registration runs, so template customization stays predictable.

Registry names are case-sensitive. A valid name begins with an ASCII letter, contains at most 128 characters, and may otherwise contain letters, numbers, _, ., or -:

^[A-Za-z][A-Za-z0-9_.-]{0,127}$

registerTemplate() ignores an invalid name and returns the registry unchanged. It throws when a valid name is paired with something other than a loader function, a { loader, render, cache, assetKey } configuration object, or an already-normalized entry. resolveTemplateEntry() falls back to Default when the requested name is absent.

The shipped starter configuration also registers HomeTemplate as a static entry backed by the Default component. That alias is project configuration, not an automatic registry default; replace or remove it when the project's route model does not use that name.

Hybrid Configuration

The loader-function signature always means client rendering. Use an object to enable SSG or SSR:

registerTemplate('HomeTemplate', {
loader: () => import('../../templates/Home'),
assetKey: 'Home',
render: 'static',
cache: {
tags: ['post-type:project']
}
});

assetKey is only needed when the registry name differs from the template filename. The render build serializes this metadata to assets/render/templates.json, which WordPress reads on direct requests.

The normalized entry keeps one in-flight loader Promise, retries after a rejected import, and retains the resolved module for later load() or preload() calls. getResolvedComponent() returns the loaded default export or null; it does not start a load by itself.

See Hybrid Rendering for server cache settings, SSG generation, SSR deployment, and route-level overrides.

See Cache Tags before adding cache.tags; tags declare data dependencies and only work when the corresponding WordPress or project event invalidates the same normalized value.

Main Helpers

The registry exposes a few important helpers:

  • registerTemplate(name, loaderOrConfiguration)
  • registerTemplates(entries)
  • resetTemplateRegistry()
  • resolveTemplateEntry(templateName)

Low-level exports also include the null-prototype templateRegistry object and createTemplateEntry(loader). They exist for framework composition and tests. Normal project code should prefer the registration helpers instead of mutating the registry object directly.

In most projects, configureTemplateRegistry.js is the only file you should need to touch.