Based on ideas previously explored in #3588 (and PR #4659) and recently discussed via @mtias in https://make.wordpress.org/core/2019/09/05/defining-content-block-areas/ (see also particularly this comment by @westonruter), let's further specify how today's paradigm of hard-coded theme template files can transition to enable full-site editing using blocks.
There are two major technical pieces needed for this:
WP_Query
instance). This issue is focused on introducing said infrastructure.Based on these two pieces, several UI decisions need to be made on how to expose these features to the user, and we will likely need some iterations to get this right. While we'll out of necessity probably touch on some of those ideas here, I suggest we focus on finding a solid under-the-hood solution first.
Here's the concrete suggestion:
wp_template
, of which each post represents a single top-level template. In other words, a template that renders an entire page's markup (to be differentiated from so-called template parts)./*.php
template file to load. Basically, each wp_template
post represents a specific one of those template files.<html>
, <head>
, wp_head
hook, <body>
opening and closing tag, etc.). Visually, it will render the actual blocks from the current template.add_theme_support()
, at least in a transitional phase.Based on this, a few further thoughts:
wp_template_part
, or an alternative variant of reusable blocks that only applies to template content (i.e. not individual post content, for better separation).index
, category
, singular
, single-product
, etc.) to the user because these are rather technical. While every theme developer has been exposed to them, they have (for a reason) never been used in WordPress UI. We will need to find a solid way for a user to understand which template they are editing, and for them to decide in which context/scope they'd like to edit the template. For an initial (experimental) implementation, it's fine to just expose block templates with these names.wp_template
post. Or it could include default block content (in place of today's template files) to use even if no user-created variant of that template exists as a wp_template
post. Or on theme activation, these wp_template
posts could be automatically created.custom-header
, widget areas, or nav menu locations probably don't make sense anymore. Other "features" like adding theme support for title-tag
could potentially be automatically enabled.We will also need a way to reuse certain "template parts". This could be accomplished with e.g. the existing reusable blocks feature, or a separate post type wp_template_part, or an alternative variant of reusable blocks that only applies to template content (i.e. not individual post content, for better separation).
I'd say a separate post type and block for template parts makes sense. The design will probably differ a lot from reusable blocks so it will be better to keep the code separated early on.
We also need to think about how themes can provide default block templates. A theme could for example provide general layouts to choose from when creating a new wp_template post. Or it could include default block content (in place of today's template files) to use even if no user-created variant of that template exists as a wp_template post. Or on theme activation, these wp_template posts could be automatically created.
See the patterns proposal: #17335.
We may want to consider keeping track of which theme was active when a given wp_template
post was created. While ideally all themes that support wp_template
should be able to simply swap out the template, some themes may have stylesheets that expect certain template block configurations. If the wp_template
posts were tagged for the active theme, then it could provide a way to filter the templates based on this. This comes to mind based on the Additional CSS feature in the Customizer, which stores CSS in a custom_css
post type, but the CSS is theme-specific so each theme gets their own dedicated custom_css
post. We were thinking at some point to provide a way to import CSS from one theme into another, and a similar idea may apply here for templates. In any case, the default case for wp_template
posts is that they should persist by default when switching themes.
- We also need to think about how themes can provide default block templates. A theme could for example provide general layouts to choose from when creating a new
wp_template
post. Or it could include default block content (in place of today's template files) to use even if no user-created variant of that template exists as awp_template
post. Or on theme activation, thesewp_template
posts could be automatically created.
Yes, a theme should provide an templates block data that get merged with wp_template
posts into the template hierarchy. Whatever is defined in wp_template
posts should override what is defined in the theme. As soon as a wp_template
is removed, then the theme-provided template data should be used. I don't think the theme-provided template data should get inserted as wp_template
posts upon activation.
When creating a wp_template
post, then you could decide to use one of the theme-provided templates block data as the starting point. Something like what @jeremyfelt shows in a tweet.
When creating a wp_template post, then you could decide to use one of the theme-provided templates block data as the starting point.
I think this is definitely a good idea - regardless of the current content of a template part, the user should be able to choose the theme's default content for that area. I think users are often confused towards why the theme's screenshot or demo looks different from their site when they activate their theme, and this would help with that.
Perhaps there could be a way for the user to choose, on theme activation, to use the default content from the theme.
I don't think the theme-provided template data should get inserted as wp_template posts upon activation.
What if a theme defines another content area for which the user doesn't have a template part yet? I can see a case for auto-populating the default content for that area in this case.
What if a theme defines another content area for which the user doesn't have a template part yet? I can see a case for auto-populating the default content for that area in this case.
Yes, in this case I believe the template part can be populated directly with data from the theme (e.g. in JSON), without needing to actually create a wp_template_part
post in the DB.
Since we already did some Full Site Editing work on WordPress.com, Iāll try to convey some of the things weāve tried so far and some of our takeaways. Iād like to preface that with a comment that our work was intentionally scoped down for two reasons:
During our work we experimented with a couple of approaches:
Hijacking the template hierarchy from the plugin.
get_template_part
, but in case of Header it pulls in <head>
tag too, and not just <header>
content.āBlank themeā approach - essentially a theme with only index.php
defined that replicates the template hierarchy using predefined page templates (in wp_template
CPTs).
Adapting existing themes to make them FSE-aware. If they detect that FSE is active, they would delegate template part rendering to it, otherwise they fall back to their default non-FSE content.
We ended up using (3) in the end, because it seemed like the most seamless way to get what we need for our scoped-down solution. While this worked for us, itās not necessarily the best long-term approach for Core, but some pieces could still be reused. This code now lives in:
Our initial template data population happens on after_switch_theme
hook, and this can work regardless of the final data storing approach. It provides a way for each theme to register its own specific template data. In order to avoid duplicating this code across all themes that want to support FSE, this functionality is now implemented in FSE plugin, but it seems like something that could be incorporated into core down the road. As a side note, we also attempt this on plugin activation, to cover the case when FSE supporting theme is already active. Overall it follows these steps:
after_switch_theme
or register_activation_hook
.maywood_header
or similar).In our case the benefit of (3) is that we donāt have to release a new theme version if we want to publish a fix or update to template data.
As a result of (2) and (5), itās possible to preserve existing customizations to template parts across theme switches. For example, if you want to just try out a couple of new themes on your site, and then revert to your original one, the previous theme specific customizations to your header would be restored.
For storing the data, we are now only using wp_template_part
CPT, but thatās just because our solution didnāt require more. When we tried to envision what core is going to do and align with that a couple of months ago, we leaned toward the wp_template
and wp_template_part
split, as opposed to just wp_template
CPT with hierarchical taxonomies. To clarify, both options seem viable from the implementation standpoint, but it seems like the former requires less wiring, might perform slightly better, and could better aligns with existing WP concepts and infrastructure. Some benefits in my opinion:
While all of the above can easily be worked around, they might hint that we are trying to clump together two conceptually different entities under the same roof, and we might discover additional work on account of that down the road too.
It seems to me like the model would become much simpler if we enforced no nesting of entities of the same type, both for wp_template
and wp_template_part
. So page template could only contain template parts, and template parts would in turn be composed of static, dynamic, and reusable blocks. Iām still not sure if this is too constraining, and it definitely requires some more thought. So something along the following lines:
P.S.: I tried to condense this as much as possible, but it still turned out a bit longer than expected - sorry about that. :) If anything is unclear because of that I'd be happy to clarify. Also, if there is any way that we can further help the core FSE work based on what we currently have on WordPress.com (be it feature testing or user feedback) feel free to let me know.
Kudos to @Copons for reviewing this and suggesting edits. ā¤
Thanks for writing this up @vindl!
During our work we experimented with a couple of approaches:
I think that a mixture of approach 1 and 2 would be optimal here. Themes should register template posts that hijack the hierarchy, but they should also be able to manually include them in PHP files. We're starting with a limited version of the former here: #17626, and of course the manual approach is always possible by including the CPT posts with custom code, but we might want to expose an explicit API for it in the future, although I also see value in just making the hijack the "supported" approach.
As a result of (2) and (5), itās possible to preserve existing customizations to template parts across theme switches.
This is something we need to do as well.
It seems to me like the model would become much simpler if we enforced no nesting of entities of the same type, both for wp_template and wp_template_part. So page template could only contain template parts, and template parts would in turn be composed of static, dynamic, and reusable blocks.
I agree, this approach also makes the most sense to me.
If I may chime in, as a person who worked hard on the WordPress.com Blank Theme experiment, and struggled immensely in explaining it to peers and stakeholders alike: we desperately need the best and clearest terminology we can come up with.
wp_template
, wp_template_part
, template hierarchy, template files: it's painfully obvious to me that the "template" word is overloaded of meanings!
I don't have a good answer, and I know this seems like bikeshedding, but if we manage to figure out some unambiguous terms, then FSE will become 100% easier to discuss, and the project itself will move forward quicker.
How about:
wp_template
s: The new "Template Posts".
wp_template_part
s: The new "Template Part Posts".
Template Hierarchy: The classic WP template hierarchy.
Template Files: The classic .php
template files.
How about:
wp_template
s: The new "Template Posts".
wp_template_part
s: The new "Template Part Posts".
Template Hierarchy: The classic WP template hierarchy.
Template Files: The classic.php
template files.
I think I was misunderstood: the meaning of each term is clear when you list them in a glossary.
But I promise you: casually mentioning, for example, wp_template
in a conversation about Full Site Editing will create major confusion and questions, depending on the level of familiarity of the people involved. š
In the end, it was inevitable to me to alwayt add a bit of description and details every time I mentioned a %template%
term for the first time in a post or comment, which in turn makes everything else less clear and harder to read and follow.
We should just link to a glossary.
Here are two more ātemplatesā:
ā¢ The block template API against which blocks are validated. (I.e. inserted blocks can be required to match the global block template and some other block components include templates)
ā¢ Starter page templates: while not in core per se, this is the case where blocks are auto-populated into a page/block area.
A glossary will definitely be important, but I do agree with @copons that unique terms for some of these would be very useful. As to what those could be though... š¤š¤
On Oct 22, 2019, 12:14 PM -0700, Enrique Piqueras notifications@github.com, wrote:
We should just link to a glossary.
ā
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.
ā¢ The block template API against which blocks are validated. (I.e. inserted blocks can be required to match the global block template and some other block components include templates)
Those are called block templates.
ā¢ Starter page templates: while not in core per se, this is the case where blocks are auto-populated into a page/block area.
Those are now being called block patterns.
Haha, yeah this will get confusing.
Those are now being called block patterns.
At least for mobile we are calling them starter page templates for now (see #18055).
Based on the conversation in #17335, I understand block patterns are meant to be parts that get inserted into a page rather than a full page template to get started.
Based on the conversation in #17335, I understand block patterns are meant to be parts that get inserted into a page rather than a full page template to get started.
A full page template can just be a pattern that gets applied automatically. Even if we decide to name them differently in the UI, I think they should share the same implementation.
@vindl I like your template diagram. Is there any reason there is a Post Content Block in the middle of the page template? Why would that not just be another template part? So... a template is just a set of template parts.
It seems reasonable as well that a template could be a combination of horizontal and vertical template parts (otherwise how would we get a sidebar!).
Before we go down the slippery slope of non-differentiation between a complex block and a template-part...I would suggest that a template-part should be a theme-specific construct while the block is a theme-agnostic construct. There was also a related discussion in https://github.com/WordPress/gutenberg/pull/18736
Thoughts?
Why would that not just be another template part?
You might not want to introduce the overhead of a template part wrapper if you are not reusing the block/set of blocks in another template.
It seems reasonable as well that a template could be a combination of horizontal and vertical template parts (otherwise how would we get a sidebar!).
Definitely, I've been exploring grids as well, #18600.
I would suggest that a template-part should be a theme-specific construct while the block is a theme-agnostic construct.
Yeah, that's how it currently works.
Cheers @epiqueras - the explanation is much appreciated. Sounds good. I concur with your comment about not needing a template part wrapper for non-reused blocks. The diagram above had made me concerned that the "post-content block" component was a hard-coded component rather than a sample "some block" as you explained above. So it sounds like a page can be all blocks, all template-parts or a combination of both...which is great. My compliments to the team. Looking forward to theming with the template-parts :-)
Exactly! Glad I could help :-)
@vindl I like your template diagram. Is there any reason there is a Post Content Block in the middle of the page template? Why would that not just be another template part? So... a template is just a set of template parts.
Thanks @timhibberd! Basically what Enrique already said. They can be both surfaced to users as Template Parts, however they are conceptually different in implementation detail in my opinion. Template Parts will be preserving their post_content
in corresponding wp_template_part
CPTs that will be reused across multiple Page Templates. On the other hand, Post Content Block will be referencing the post_content
of the current post being rendered, so it doesn't require the same scaffolding and data storage as Template Parts do. Another way to formulate the difference would be to say that Template Parts are reusable and static (although they can still contain dynamic blocks), and Post Content Block is reusable and dynamic.
It seems reasonable as well that a template could be a combination of horizontal and vertical template parts (otherwise how would we get a sidebar!).
That's true! I wanted to keep my example as simple as possible, so I left those out, but I didn't foresee any problems with incorporating them into the above model. My main intention was to represent the data relationships and the way they are stored. That Page Template in the diagram also has some resemblance to the actual layout, so I see how that could've been misleading. In any case, even in the above example, any (or both) of the Template Parts could be styled and presented visually as horizontal ones, turning that into a 2 (or 3) column page layout.
Before we go down the slippery slope of non-differentiation between a complex block and a template-part...I would suggest that a template-part should be a theme-specific construct while the block is a theme-agnostic construct.
I'm not sure if I'm interpreting this part correctly and to which extent it should apply, but I think that this kind of separation could be useful. My addition of theme specific taxonomy terms in the diagram (wp_template_theme
and wp_template_part_theme
) was partly motivated by that.
Cheers @vindl - much appreciated :-) I hope my comments came across as intended...to elicit clarifications (which you and Enrique did clarify nicely). I thought your proposal and diagram were spot-on.
Regarding my comment about differentiation between a complex block and a template-part, I think you and Enrique have clarified that. My comment was intended to ensure that we can answer the question: "What is / are the difference(s) between a complex block and a template-part?". The definition of a "theme" in the Gutenberg era is still emerging and the answer to this question will, in part, help existing theme designers to make the mental shift from the old world to the new world.
Most of the architecture work for this issue has already landed. I'm going to close this issue now, let's focus on smaller targetted issues now.
we have launched a number of sites using wp_template custom post types.
we cannot get woocommerce pages to override using this method.
any ideas or tips? we are desperate. thanks!
@JoshuaJarman you might want to start a new issue, instead of posting to a closed issue.
It then will also guide you through some information needed to actually assist in what goes wrong. And what you already tried to fix it. Be as specific as you can with code examples etc.
@bph i'll try again. even mentioning the block templates and custom post_type wp_templates and its routing seems to confuse most people, so i hoped to ask in one of the few corners where people know anything about it.
I responded on #24129 :)
Most helpful comment
Since we already did some Full Site Editing work on WordPress.com, Iāll try to convey some of the things weāve tried so far and some of our takeaways. Iād like to preface that with a comment that our work was intentionally scoped down for two reasons:
During our work we experimented with a couple of approaches:
Hijacking the template hierarchy from the plugin.
get_template_part
, but in case of Header it pulls in<head>
tag too, and not just<header>
content.āBlank themeā approach - essentially a theme with only
index.php
defined that replicates the template hierarchy using predefined page templates (inwp_template
CPTs).Adapting existing themes to make them FSE-aware. If they detect that FSE is active, they would delegate template part rendering to it, otherwise they fall back to their default non-FSE content.
We ended up using (3) in the end, because it seemed like the most seamless way to get what we need for our scoped-down solution. While this worked for us, itās not necessarily the best long-term approach for Core, but some pieces could still be reused. This code now lives in:
Populating and storing template data
Our initial template data population happens on
after_switch_theme
hook, and this can work regardless of the final data storing approach. It provides a way for each theme to register its own specific template data. In order to avoid duplicating this code across all themes that want to support FSE, this functionality is now implemented in FSE plugin, but it seems like something that could be incorporated into core down the road. As a side note, we also attempt this on plugin activation, to cover the case when FSE supporting theme is already active. Overall it follows these steps:after_switch_theme
orregister_activation_hook
.maywood_header
or similar).In our case the benefit of (3) is that we donāt have to release a new theme version if we want to publish a fix or update to template data.
As a result of (2) and (5), itās possible to preserve existing customizations to template parts across theme switches. For example, if you want to just try out a couple of new themes on your site, and then revert to your original one, the previous theme specific customizations to your header would be restored.
For storing the data, we are now only using
wp_template_part
CPT, but thatās just because our solution didnāt require more. When we tried to envision what core is going to do and align with that a couple of months ago, we leaned toward thewp_template
andwp_template_part
split, as opposed to justwp_template
CPT with hierarchical taxonomies. To clarify, both options seem viable from the implementation standpoint, but it seems like the former requires less wiring, might perform slightly better, and could better aligns with existing WP concepts and infrastructure. Some benefits in my opinion:While all of the above can easily be worked around, they might hint that we are trying to clump together two conceptually different entities under the same roof, and we might discover additional work on account of that down the road too.
It seems to me like the model would become much simpler if we enforced no nesting of entities of the same type, both for
wp_template
andwp_template_part
. So page template could only contain template parts, and template parts would in turn be composed of static, dynamic, and reusable blocks. Iām still not sure if this is too constraining, and it definitely requires some more thought. So something along the following lines:P.S.: I tried to condense this as much as possible, but it still turned out a bit longer than expected - sorry about that. :) If anything is unclear because of that I'd be happy to clarify. Also, if there is any way that we can further help the core FSE work based on what we currently have on WordPress.com (be it feature testing or user feedback) feel free to let me know.
Kudos to @Copons for reviewing this and suggesting edits. ā¤