A Template is a page archetype that is a WordPress page template and owns the
module region — it decides whether a module region exists at all and how Modules are
composed into the page. The default template appends Modules to the_content; OneFold
runs its own loop over a dedicated field. Choosing a Template is choosing the page's
whole composition strategy.
Examples: OneFold, SinglePost.
Three facets
A Template travels as three colocated facets.
1. The App\Templates\* class
Extends BaseTemplate, names itself, declares which Modules it allows, and renders:
// app/Templates/OneFold.php
class OneFold extends BaseTemplate
{
public function name(): string
{
return 'One-Fold';
}
public function modules(): array|false
{
return [Masthead::class, Message::class, ContactForm::class];
}
public function render(): void
{
View::template('one-fold', [
'template' => $this,
'modules' => get_field('one-fold_modules'),
'ribbon' => get_field('ribbon'),
]);
}
}
modules() is the Template's defining power: it restricts the palette of Modules an
author can place. render() resolves the Template's own view and hands it the Template's
own field data — including one-fold_modules, a module region that is not the default
the_content loop.
The WordPress page-template file wires the class into the render:
// template-one-fold.php
/* Template Name: One-Fold */
get_header('one-fold'); ?>
<div id="app">
<?php (new OneFold())->render(); ?>
</div>
<?php get_footer('one-fold');
The view then runs the region itself:
// resources/public/views/templates/one-fold.php
if (have_rows('one-fold_modules')) {
while (have_rows('one-fold_modules')) {
the_row();
$class = get_sub_field('module_class');
if (! class_exists($class)) continue;
(new $class())->render();
}
}
That have_rows loop is the point of the whole category: the Template owns the module
region. Where the default template appends Modules to post content, OneFold decides
the region is its own one-fold_modules field and drives the loop by hand.
2. The .page-template-* body class
WordPress adds a body class per active page template. That class is the Template's selector — how its asset finds the page:
static selector = '.page-template-template-one-fold'
3. The colocated asset
Often behaviourless. A Template usually needs no runtime logic — it just needs its
styles in the bundle. OneFold is a CSS-only component: nothing but a selector, so
importing it pulls its SCSS in via the JS import side-effect.
// resources/public/assets/templates/OneFold/OneFold.js
import "./OneFold.scss"
class OneFold extends Instantiable {
static selector = '.page-template-template-one-fold'
}
const Final = new Traits(OneFold, [])
export { Final as OneFold }
CSS-only component. An Instantiable with only
a static selector and no lifecycle. Its entire job is to make the loader download the
chunk so the colocated .scss applies. It registers in a loader like anything else —
OneFold has a Deferred.js entry keyed to .page-template-template-one-fold — but it
boots to a no-op instance whose only lasting effect is the imported CSS. Reach for this
whenever an archetype needs styles but no behaviour.
Template vs Layout vs Module
- A Template owns the region Modules compose into — it's a property of the page you pick in the editor's Template dropdown.
- A Layout frames that region from outside and is emitted by the shell regardless of Template.
- A Module is placed inside the region the Template owns.
Related
- Modules — what a Template's region composes.
- Layouts — the chrome that frames the Template's region.
- Instantiable & the instance model — the base a CSS-only asset still extends.
- Two-phase loading — where a Template's asset registers.