You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Not a proposal. This records a discussion so the reasoning exists somewhere and does not have to be rebuilt from scratch the next time the question comes up — which it will, because the platform keeps moving.
The question that started it: should Twig templates eventually be transformed into native block templates, so the stack sits closer to the WordPress standard?
What a block template actually is
Worth stating plainly, because the word "template" invites the wrong expectation. An FSE .html template is block markup, not a template language. It has no variables, no macros, no conditionals, no loops, and no parameterised includes. Composition comes from exactly three mechanisms:
template parts — an include, with no parameters
patterns — an include, with no parameters
blocks — the real unit of reuse; a block with attributes is the FSE equivalent of a Twig macro with arguments
That last equivalence is functionally fair and economically very different. Where a macro is three lines in a .twig file, a block is a registration, an editor UI, and a render callback.
Block Bindings (WP 6.5+, still developing) is closing the "no variables" gap by binding block attributes to sources. It is the fastest-moving part of FSE, which makes "revisit in a year" a real strategy rather than procrastination.
Twig would not disappear
The important structural fact. ACF blocks render through BlockRenderer, which calls Timber::context() (src/BlockRenderer.php:322). In a full block theme that stays true.
So a migration would not remove Twig. It would demote it: Twig stops being the language of page assembly and remains the language of block internals. Everything that makes Twig worth having here — macros, shared partials, the image component and its resizing machinery (Resizer.php, DevMediaProxy.php) — lives inside blocks, not at page level. The layer being valued is not the layer FSE would replace.
That also identifies a clean seam, and distinguishes it from the hybrid worth avoiding:
Dangerous hybrid:block-template-parts bolted onto a classic theme. FSE and Twig then own the same page region, and nobody can tell which wins. It fails late and quietly — the template-part editor works, someone edits a part, and the front end does not change, because Twig renders that region.
Coherent layering: a block theme where FSE owns page assembly and Twig owns block internals. One owner per layer.
The decision is about ownership, not syntax
Block templates are editable in wp-admin, and once edited they are stored in the database as wp_template posts that override the theme file. That is the entire point of FSE. It is also a significant operational change for an agency: a client edit silently supersedes the deployed template, and the next deploy does not fix it, because the file is no longer the source of truth.
Today the layout is in git and git is the only truth. Whether that is worth trading is the first question to answer, because everything else follows from it.
The locking paradox
The natural reaction is: lock the templates so they cannot be overridden, keeping theme files 1:1. That is achievable:
Capabilities — wp_template maps to edit_theme_options. A role without it cannot reach the Site Editor. This is the supported route.
Block-level locks — lock: { move: true, remove: true } on blocks inside a template constrains even those who can open it.
Hard block on wp_template writes — possible via filters, but outside the supported surface; last resort.
Core also offers a brake rather than a lock: a customised template is flagged in admin and "Clear customizations" reverts it to the theme file.
But locking the templates removes the only reason to migrate. Editability is the value. Remove it and what remains is the cost: no macros, no variables, no conditionals, and every small component promoted to a registered block.
Locked block templates and Twig templates do the same job — layout in git, editors kept out. Twig does it more comfortably.
Migration therefore only makes sense if the goal is standardisation rather than editability: portability between developers, alignment with core, familiarity for people who do not know this stack. That is a legitimate goal. It is a different goal, and it leads to different decisions than "the client should be able to change the footer".
What the wish for locking usually means
When "can I lock the templates?" comes up, it generally signals that the real need is not an editable template but an editable region. That is #94: layout stays in git, 1:1 with the theme, and only explicitly declared slots are editable. It delivers the useful half of FSE with no migration and no loss of control over the rest.
Criteria for revisiting
Worth re-opening this when one of these changes:
Block Bindings reaches the point where a page-level template can express what a Twig template expresses today without a custom block per variation.
Team composition changes such that Twig knowledge becomes the bottleneck rather than an asset.
Core provides a supported way to keep templates authoritative in the theme while still allowing scoped editing — which would dissolve the paradox above.
Until one of those holds, the reasoning above says: keep Twig for assembly and for block internals, and put editability where it is actually wanted, region by region.
Not a proposal. This records a discussion so the reasoning exists somewhere and does not have to be rebuilt from scratch the next time the question comes up — which it will, because the platform keeps moving.
The question that started it: should Twig templates eventually be transformed into native block templates, so the stack sits closer to the WordPress standard?
What a block template actually is
Worth stating plainly, because the word "template" invites the wrong expectation. An FSE
.htmltemplate is block markup, not a template language. It has no variables, no macros, no conditionals, no loops, and no parameterised includes. Composition comes from exactly three mechanisms:That last equivalence is functionally fair and economically very different. Where a macro is three lines in a
.twigfile, a block is a registration, an editor UI, and a render callback.Block Bindings (WP 6.5+, still developing) is closing the "no variables" gap by binding block attributes to sources. It is the fastest-moving part of FSE, which makes "revisit in a year" a real strategy rather than procrastination.
Twig would not disappear
The important structural fact. ACF blocks render through
BlockRenderer, which callsTimber::context()(src/BlockRenderer.php:322). In a full block theme that stays true.So a migration would not remove Twig. It would demote it: Twig stops being the language of page assembly and remains the language of block internals. Everything that makes Twig worth having here — macros, shared partials, the image component and its resizing machinery (
Resizer.php,DevMediaProxy.php) — lives inside blocks, not at page level. The layer being valued is not the layer FSE would replace.That also identifies a clean seam, and distinguishes it from the hybrid worth avoiding:
block-template-partsbolted onto a classic theme. FSE and Twig then own the same page region, and nobody can tell which wins. It fails late and quietly — the template-part editor works, someone edits a part, and the front end does not change, because Twig renders that region.The decision is about ownership, not syntax
Block templates are editable in wp-admin, and once edited they are stored in the database as
wp_templateposts that override the theme file. That is the entire point of FSE. It is also a significant operational change for an agency: a client edit silently supersedes the deployed template, and the next deploy does not fix it, because the file is no longer the source of truth.Today the layout is in git and git is the only truth. Whether that is worth trading is the first question to answer, because everything else follows from it.
The locking paradox
The natural reaction is: lock the templates so they cannot be overridden, keeping theme files 1:1. That is achievable:
wp_templatemaps toedit_theme_options. A role without it cannot reach the Site Editor. This is the supported route.add_filter( 'block_editor_settings_all', … )setting$settings['supportsTemplateMode'] = false;closes the side-panel route.lock: { move: true, remove: true }on blocks inside a template constrains even those who can open it.wp_templatewrites — possible via filters, but outside the supported surface; last resort.Core also offers a brake rather than a lock: a customised template is flagged in admin and "Clear customizations" reverts it to the theme file.
But locking the templates removes the only reason to migrate. Editability is the value. Remove it and what remains is the cost: no macros, no variables, no conditionals, and every small component promoted to a registered block.
Locked block templates and Twig templates do the same job — layout in git, editors kept out. Twig does it more comfortably.
Migration therefore only makes sense if the goal is standardisation rather than editability: portability between developers, alignment with core, familiarity for people who do not know this stack. That is a legitimate goal. It is a different goal, and it leads to different decisions than "the client should be able to change the footer".
What the wish for locking usually means
When "can I lock the templates?" comes up, it generally signals that the real need is not an editable template but an editable region. That is #94: layout stays in git, 1:1 with the theme, and only explicitly declared slots are editable. It delivers the useful half of FSE with no migration and no loss of control over the rest.
Criteria for revisiting
Worth re-opening this when one of these changes:
Until one of those holds, the reasoning above says: keep Twig for assembly and for block internals, and put editability where it is actually wanted, region by region.
Related
portadesign/portadesign-mcp#182,portadesign/portadesign-mcp#183— the same code/content boundary seen from the MCP connector's side.