Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Block Themes and site editor: Refactoring templates #66950

Open
youknowriad opened this issue Nov 13, 2024 · 25 comments · May be fixed by #67125
Open

Block Themes and site editor: Refactoring templates #66950

youknowriad opened this issue Nov 13, 2024 · 25 comments · May be fixed by #67125
Labels
[Feature] Site Editor Related to the overarching Site Editor (formerly "full site editing") [Feature] Templates API Related to API powering block template functionality in the Site Editor [Feature] Themes Questions or issues with incorporating or styling blocks in a theme. [Type] Overview Comprehensive, high level view of an area of focus often with multiple tracking issues

Comments

@youknowriad
Copy link
Contributor

youknowriad commented Nov 13, 2024

Description

Since the introduction of block themes, the mental model has been that these themes provide interconnected entities (templates, styles, patterns) that the user can edit in the UI.

This mental model has proven challenging. The main problem is that from a user’s perspective, the difference between theme entities and user-created ones is blurred. We show templates from files and database ones in the same list. This means we have to create a custom abstraction that refers to files in some situations or custom post types in others.

Other challenges include:

  • Losing access to edited user templates when switching themes, because they’re theme-specific.
  • Losing template revisions when users click “reset template customizations.”
  • “Reset template customizations” has proven to be a hard-to-understand interaction for users.
  • Enabling use-cases like creating and switching alternative templates (like selecting a front page template) becomes difficult.
  • We can’t create a paginated REST API for templates because pagination and filtering need to merge them from the database and files or PHP registration.

Proposal

We can address these problems for the future by adapting our mental model regarding these theme-provided entities.

Rather than users editing theme provided entities, this proposal explores creating custom ones and assigning them as replacement to the default provided ones.

In simpler terms for templates, it means:

  • Users can create templates, name them, and assign them to the “template hierarchy.”
  • By default, themes’ templates are “auto-assigned” to the template hierarchy slugs, acting as fallbacks.
  • Users can use theme-provided templates as starting points for creating custom templates.

The biggest UX impact for existing FSE users and the site editor are:

  • We must render the default templates from themes in a non-editable but “forkable” list.
  • User templates will be displayed in a separate list from registered ones. This eliminates confusion in the current template list with some selectable items having bulk action, while others don’t.
  • Users can freely assign and modify templates to specific hierarchy slugs.

This change automatically resolves the mentioned challenges and issues:

  • User-created or edited templates will persist when the user switches themes.
  • Users can reset the default theme’s templates as active.
  • The confusing “reset template customization” action is no longer needed.
  • You can mix and match templates from different sources, and show templates from multiple themes or template packs.
  • Switching active front pages or templates becomes easy.

Technically, this is not a significant change compared to what exists today:

  • A new site option is needed to store the “active template hierarchy slugs”. Think of it as an associative array where the keys are template slugs, and the values are the template id. If no id is assigned, the default theme template is used.
  • Switch from the existing REST API endpoint for “templates” to the default Core post endpoints to fetch and edit them.

For backward compatibility:

  • When this behavior is enabled, a simple database upgrade migration is needed to fill the “active template hierarchy slugs” site option using the existing user templates.
  • The current template endpoint will remain for retrieving registered templates, and editing capabilities can be deprecated. The simpler post endpoint will be used for user templates.
  • What about other entities (template parts, patterns, and styles) from themes?

Applying the same mindset makes implementing desired features for these entities easier. Examples unlocked:

  • Unifying patterns and template parts (areas or slots support for patterns and phasing out template parts)
  • Allowing pattern overrides in themes
  • Creating and editing style variations
  • Assigning style variations to pages and templates.

(This proposal is from both me and @ellatrix)

@youknowriad youknowriad added [Feature] Site Editor Related to the overarching Site Editor (formerly "full site editing") [Feature] Templates API Related to API powering block template functionality in the Site Editor [Feature] Themes Questions or issues with incorporating or styling blocks in a theme. [Type] Overview Comprehensive, high level view of an area of focus often with multiple tracking issues labels Nov 13, 2024
@fabiankaegy
Copy link
Member

fabiankaegy commented Nov 13, 2024

Hey @youknowriad and @ellatrix 👋

Thanks so much for this proposal. I feel like I have an understanding of what you suggest but let me rephrase it in a few different ways back at you to see If I have the nuance right :)

In this new world a theme would still be able to define any template defined in the theme template hierarchy as .html files located inside the templates directory. In the site editor we would surface a list of all these templates. If a user wants to make modifications to any of these templates they would need to click a "fork" button which would then create a copy of that template in the DB and show it in a separate listing.

As an additional layer all these user generated template overrides have some maüpping UI where the user can map any template to a specific spot in the template hierarchy? A user could then, at any point, reset the mapping to use the original theme template again without having to delete their custom version.

What I am unsure about is where this would leave template parts? Would they work the same? Or would they get further absorbed into just being patterns that get referenced via a slug? Where we are at today there still is a big difference between patterns and template parts because template parts essentially are synced theme patterns 🤔


If what I stated above is correct, I have a few initial concerns that I would love to run by you:

  1. I do think that it is a nice goal to retain user modifications when switching from one theme to another. But in reality I don't see how this will actually work. Especially for templates. Because at the end of the day themes contain color, typography, and spacing tokens that are not standardized. Any theme can name their presets any random name (which I don't think we ever can nor should change). So switching a theme whilst keeping a users generated template override active in my opinion will lead to a more frustrating experience because the visual appearance of the template is most likely going to be broken. (This is not a concern that impacts my line of work much as we build custom purpose themes that don't get swapped out randomly so maybe I'm wrong here :))
  2. Have you given any thought to how the developer experience of creating & editing a theme could work in this new paradigm? With today's template overrides system the create-block-theme plugin has created a very easy editorial flow where you simply make updates to the templates in a local environment and hit one button to persist the changes back to disk. Whatever we come up with here should work closely with the create block theme team to ensure we can support similar flows as no one wants to hand author the block markup inside template files =D
  3. How would this work for page templates. Most designs I work on use several custom page templates (for various post types) that the user can switch between via the template switcher in the sidebar. If a user chooses to "fork" one of these page templates how would we resolve the correct override here for all the old existing posts that already exist and have that page template selected?
  4. Currently, admins can double-click on any template in the editor (or use the template dropdown) to start editing the current template. How would that work here? I guess it could still create this new custom template post and make the connection to replace the theme template in the hierarchy.

Having said all that, I do believe that, especially for the enterprise workflows that I am describing and that I have "complained" about this would be a big step forward. The greater clarity about what is coming from the user vs. what is coming from the theme is going to help a lot.

I would almost love to see a new editor setting/user-capability/filter that would allow us to simply remove the ability to fork any templates/template parts on a production site. However in order to get there, there is more work needed to be able to have things like the navigation block work something more like "menu-locations" that we had in classic themes.

Like I said before, I do thing working closely with the Create Block Theme team is going to be crucial here, as we need a way to use the site editor as a kind of visual IDE to make changes to templates that we can write back to disk.

(as you may have noticed most of my concerns are actually about end user issues. Not things that would impact us much on the custom build client side front :))

@youknowriad
Copy link
Contributor Author

What I am unsure about is where this would leave template parts? Would they work the same? Or would they get further absorbed into just being patterns that get referenced via a slug? Where we are at today there still is a big difference between patterns and template parts because template parts essentially are synced theme patterns

I have a separate proposal that I've been thinking about for template parts, and the idea is to just become patterns while patterns gain more powers (areas or slots). It has some nuance so I wanted to first get the discussion rolling about templates.

I do think that it is a nice goal to retain user modifications when switching from one theme to another. But in reality I don't see how this will actually work. Especially for templates. Because at the end of the day themes contain color, typography, and spacing tokens that are not standardized. Any theme can name their presets any random name (which I don't think we ever can nor should change). So switching a theme whilst keeping a users generated template override active in my opinion will lead to a more frustrating experience because the visual appearance of the template is most likely going to be broken. (This is not a concern that impacts my line of work much as we build custom purpose themes that don't get swapped out randomly so maybe I'm wrong here :))

I think it's fair to say that we received that feedback a lot of time that it's clear that it's a struggle for people. We might not want to retain the templates as active by default when switching but allowing people to enable these templates after switching is definitely something people have asked about. It is true that there are some challenges there related to links to styles and parts but these are solvable issues given the fact that all block themes work in the same way.

Have you given any thought to how the developer experience of creating & editing a theme could work in this new paradigm? With today's template overrides system the create-block-theme plugin has created a very easy editorial flow where you simply make updates to the templates in a local environment and hit one button to persist the changes back to disk. Whatever we come up with here should work closely with the create block theme team to ensure we can support similar flows as no one wants to hand author the block markup inside template files =D

Yes, I don't think it's more complex. It feels like it's actually simpler now, you take the active templates and persist them into the files and remove all the non active ones. We could even supporting disabling "theme templates" that don't have overrides which is not possible with today's paradigm.

How would this work for page templates. Most designs I work on use several custom page templates (for various post types) that the user can switch between via the template switcher in the sidebar. If a user chooses to "fork" one of these page templates how would we resolve the correct override here for all the old existing posts that already exist and have that page template selected?

I think we can probably make the page templates defined by themes as "slugs" that user templates can be assigned to.

Currently, admins can double-click on any template in the editor (or use the template dropdown) to start editing the current template. How would that work here? I guess it could still create this new custom template post and make the connection to replace the theme template in the hierarchy.

Did you check the video in the related PR. I think it becomes clearer there.

I would almost love to see a new editor setting/user-capability/filter that would allow us to simply remove the ability to fork any templates/template parts on a production site. However in order to get there, there is more work needed to be able to have things like the navigation block work something more like "menu-locations" that we had in classic themes.

I agree that a capability like that would be a great addition.

Like I said before, I do thing working closely with the Create Block Theme team is going to be crucial here, as we need a way to use the site editor as a kind of visual IDE to make changes to templates that we can write back to disk.

Definitely, I think "Create Block Theme" should not be needed ideally and the export capability should be improved in Core with learnings from Create Block Theme.

@fabiankaegy
Copy link
Member

Definitely, I think "Create Block Theme" should not be needed ideally and the export capability should be improved in Core with learnings from Create Block Theme.

As long as we can have it persist to disk instead of exporting a ZIP file I don't care where the code lives 😆

@fabiankaegy
Copy link
Member

fabiankaegy commented Nov 13, 2024

Currently, admins can double-click on any template in the editor (or use the template dropdown) to start editing the current template. How would that work here? I guess it could still create this new custom template post and make the connection to replace the theme template in the hierarchy.

Did you check the video in the related PR. I think it becomes clearer there.

I missed that. This is really cool to see! And yeah that makes it a lot more clear.

Could we maybe even allow themes to contain multiple versions of a template that users could then activate? Thinking it would be a really powerful addition if that can even get automated / scheduled / programmatically changed 🤔

Like imaging if a theme could ship with a Christmas and a Halloween version of the homepage like you showed the user creating there and then being able to manage which version you want to become active at which point of time. Maybe even automatically tied to the calendar 🤯

@youknowriad
Copy link
Contributor Author

Could we maybe even allow themes to contain multiple versions of a template that users could then activate? Thinking it would be a really powerful addition if that can even get automated / scheduled / programmatically changed 🤔

Yes, that's a nice idea that becomes possible, we need to find a way to define that flag in themes (other than using file names)

@fabiankaegy
Copy link
Member

Could we maybe even allow themes to contain multiple versions of a template that users could then activate? Thinking it would be a really powerful addition if that can even get automated / scheduled / programmatically changed 🤔

Yes, that's a nice idea that becomes possible, we need to find a way to define that flag in themes (other than using file names)

Or literally using file names? If we have a mapping for all the core template hierarchy options the default for front-page would be front-page.html with a fallback for front-page.php. But if a user sets that option to my-custom-christmas-front-page.html that should still resolve and let core know what file should be used for which template?

And for custom templates they would be their own thing like they already are since users manually map those to content

@youknowriad
Copy link
Contributor Author

my-custom-christmas-front-page.html Why is this not a "page.html" template :). I'm not sure if files names are enough, they might create confusion with custom page templates as well.

Personally, I would love to be able to define metadata within the file (comment at the top of the file just like we do in php).

@fabiankaegy
Copy link
Member

my-custom-christmas-front-page.html Why is this not a "page.html" template :). I'm not sure if files names are enough, they might create confusion with custom page templates as well.

Personally, I would love to be able to define metadata within the file (comment at the top of the file just like we do in php).

Yeah the fact that we have to update theme.json every time we add a custom template / template part is really cumbersome 😅

@ellatrix
Copy link
Member

I do think that it is a nice goal to retain user modifications when switching from one theme to another. But in reality I don't see how this will actually work.

Yeah, we talked about this. I think we might have to unset all active user templates when you switch the theme as a whole. Otherwise if you have a lot of customisations, you also wouldn't see the new theme. If desired, the user could re-activate certain custom templates (usually ones started from scratch).

Have you given any thought to how the developer experience of creating & editing a theme could work in this new paradigm?

Nothing needs to change there.

How would this work for page templates.

You can assign a duplicated template to custom page template slugs. Actually another benefit of this is that you can also assign a duplicated custom page template to act is the general page template. But you can also assign it to the custom page template slug from the theme.

Could we maybe even allow themes to contain multiple versions of a template that users could then activate? Thinking it would be a really powerful addition if that can even get automated / scheduled / programmatically changed 🤔

Totally! This enables scheduling templates, just like posts! :)


And I think it would be nice if themes provide alternatives for a certain template and allow users to switch between them as a default page/post template. Currently that's not possible.

Another benefit is that you can now click "Add new template" and create a completely new template for any slug, not just the missing ones.

And another benefit! :) These new custom templates are now stored as drafts. In trunk, they are immediately active and take over the live site. With this, you can work on your template and activate it later.

@nerrad
Copy link
Contributor

nerrad commented Nov 13, 2024

This could provide a more intuitive path to surface options for creating/assigning new templates across custom post types or slugs registered by plugins.

Might be too in the weeds to consider this yet, but with the "assign to slug" (or something similar) model - we should consider somehow providing the associated query context with that slug: post type archive, post type posts archive, single post data, taxonomy archive, taxonomy term archive, menu, index, {custom_route}. This allows for cleaner context awareness (i.e. archive vs single post, custom post types etc).

@Aljullu
Copy link
Contributor

Aljullu commented Nov 13, 2024

I'm also curious to know if you had something in mind in the case a plugin and a theme register the same template.

A couple of questions that come to my mind:

  • Would the plugin template be listed in the plugin-specific templates view even if it's overridden by a theme template? The benefit of that is that users would be able to "Duplicate" the template from the theme or the plugin independently.
  • And would users be able to "Activate" the plugin template to have priority over the theme one?

I don't have a strong opinion on any of the two, but I lean towards making both possible: allowing to "Duplicate" the plugin template and also allowing it to be "Activated" over the theme template.

@youknowriad
Copy link
Contributor Author

I'm also curious to know if you had something in mind in the case a plugin and a theme register the same template.

Yes, essentially "plugins and theme" templates behave the same way, they are "registered templates": The user can disable them, active them, duplicate them and assign user template to their slugs. When it comes to priority, it's not that important, we can pick one if there's no explicit assignment in the site option.

@Aljullu
Copy link
Contributor

Aljullu commented Nov 13, 2024

Yes, essentially "plugins and theme" templates behave the same way, they are "registered templates": The user can disable them, active them, duplicate them and assign user template to their slugs. When it comes to priority, it's not that important, we can pick one if there's no explicit assignment in the site option.

Makes sense. Some things from the current behavior will need to be updated, though. Currently, when a theme overrides a plugin-registered template, we don't display it alongside the plugin templates anymore. With this new proposal, it will make more sense if both the theme template and the plugin template are listed in the Site Editor. This way each one of them can be duplicated or activated.

I guess it's similar to the logic that will need to be updated so theme templates that are overridden by user templates are displayed too. But wanted to highlight it just in case. 🙂

@talldan
Copy link
Contributor

talldan commented Nov 14, 2024

I haven't read through the whole comments, so sorry if I'm repeating some things.

What about other entities (template parts, patterns, and styles) from themes?

Navigation also feels like a big one, since I know @getdave was pretty keen to tackle the migration to the block and entity using a slug instead of an id. This could completely change how that's approached. If I'm right, we may not have to introduce slugs to the post type, we can instead associate the existing ids with a slug like identifier that the block stores (or template area). Having said this, I'm not sure navigation will be the best one to start with. Maybe templates and template parts first, the template part implementation might inform the navigation one.

What's funny is that the navigation block worked very much like this in an earlier iteration, but the idea of storing the entity association data in the database was a bit too different to how everything else worked in the site editor at the time. There was also a Navigation Area block which introduced a lot of complexity in block selection. I think we've learnt enough to implement this in a better way, and if all the other entities work the same way it'll help bring consistency.

This change automatically resolves the mentioned challenges and issues:

If I'm understanding it correctly, I think also it should be possible to lookup where entities are used (#60205), so it may also help solve that issue. I guess it wouldn't be an exact count of 'this many posts', but instead it'd be that the entities are assigned to this 'name' in the template hierarchy which may exist in multiple posts.

@sethrubenstein
Copy link
Contributor

I just wanted to chime in and say I generally support these changes. It sounds like this would offer more flexibility and provide an opportunity to rethink local template file management, particularly regarding metadata. I'll second that updating theme.json with the correct template titles and associated post types can be cumbersome. It would be definitely be better if we could include metadata directly in the file, like /patterns/my-pattern.php files.

That said, if this does impact Template Parts as well I just want to reiterate my concern in #65698. I'm worried that Template Parts may be hastly subsumed by Patterns without addressing block context scope. Currently, Template Parts maintain block context during editing, while Synced Patterns do not as they enter a more focused editing mode. If Template Parts simply become basically Synced Patterns, it could negatively impact any custom blocks that depend on block context from a higher-level block when in the Site Editor.

@youknowriad
Copy link
Contributor Author

Currently, Template Parts maintain block context during editing, while Synced Patterns do not as they enter a more focused editing mode.

When you say "block context" here, can you clarify a bit more ? I'm failing to understand how template parts are different than patterns here?

@sethrubenstein
Copy link
Contributor

sethrubenstein commented Nov 15, 2024

@youknowriad, I mean just normal ol' block api block context. For example: Here, you'll see several console logs for our various facet-template blocks. These logs provide information about the available facets via block context from a higher-level block. These facet-template blocks are located in a template part, allowing us to share this set and use it in multiple places. In template parts, you can edit directly, so block context is passed down to other blocks without issue. However, when you edit a Synced Pattern, it takes you to an isolated editing mode where it loses block context since it is no longer within any blocks. As a result, our block becomes unusable in this situation.

CleanShot.2024-11-14.at.19.38.29.mp4

@talldan
Copy link
Contributor

talldan commented Nov 15, 2024

In template parts, you can edit directly, so block context is passed down to other blocks without issue. However, when you edit a Synced Pattern, it takes you to an isolated editing mode where it loses block context since it is no longer within any blocks. As a result, our block becomes unusable in this situation.

@sethrubenstein It's an interesting example. Looking at list view in your example, it seems like the template part (Standard shared facets) might have a dependency on Facets Context Provider. I guess that affects the portability of the template part and you can't insert it anywhere? I'm not sure what kind of data the Facets are, but is it also possible to configure the template part in a way that makes it incompatible with other Facets Context Providers?

I think this is a very similar situation to building post templates - the editor doesn't provide a post's data while doing that, instead there are placeholder values for things like the post title, featured image and post content. It could also be argued that it's useful to have real world data when editing this as well, or it could also be possible to build a template that relies on some post meta, and that affects its ability to be applied to different post types.

It's really the same set of problems across templates, template parts and patterns. 😄

@mtias
Copy link
Member

mtias commented Nov 17, 2024

Hear, hear. Looking great! While reviewing this proposal I didn't feel this was a departure from how things have been modeled so far, and more of a clarification. I think that's important to bring up since it accounts for gradual evolution and backwards compatibility.

The current UI makes it seem like users are editing the templates from a theme, but in reality they were always creating custom templates saved as user content. The loading and merging flows were opinionated only because we lacked a robust assignment flow, so user templates always "won" and the way to restore the theme state was to remove / reset. But that was just an interim state in my mind. As we expand the management of templates, including plugin ones, it stands to reason that the objects need a more explicit assignment.

I think this moves things in the right direction. I'd love to apply the same mental model to style objects, both saved in the global styles post type and in the theme file system.

Some considerations that come to mind:

  • Ensure we provide the ability to disable / deactivate individual templates from a theme without having to fork them.
  • The UX of "fork" "duplicate" can become confusing from a user perspective, we need to be mindful of that.
  • Let's consider "active templates" and "virtual pages" part of the same problem space—we need to give visibility in the pages views.
  • Workflows to save directly into theme files or similar version control workflows (like create block theme) should be supported and governed by permissions (edit theme vs theme files, etc), accounting for multi-site, etc.
  • To also consider activation / setup—allow themes to have multiple templates of a kind and offer users a way to pick a default on setup.

@jameskoster
Copy link
Contributor

Nice, a lot of potential here :) A couple of thoughts on areas that might need some design:

  • The current data view UX around theme Patterns could use some love. Improvements there will benefit this effort too. This can begin now.
  • How much of the existing UI can we use? For instance can the current 'Add template' modal serve as the UI for 'assigning templates to the hierarchy'?
  • Should we be opinionated about hierarchy assignment based on the duplicated template? E.g. if you duplicate 404 do we still ask how you want to assign that template?
  • In cases where there are many templates it would be useful to have 'in use' / 'not in use' flags. This should be filterable in data views.

Where there any other pieces you had in mind for design?

@carolinan
Copy link
Contributor

carolinan commented Nov 20, 2024

Could we maybe even allow themes to contain multiple versions of a template that users could then activate?

We do this today by adding patterns with the Template Types parameter.

@carolinan
Copy link
Contributor

carolinan commented Nov 20, 2024

Why is the base template provided by an installed and active theme and not core?
If a user creates templates in the database, and activates them, the theme files are not needed.

@justintadlock
Copy link
Contributor

What about other entities (template parts, patterns, and styles) from themes?
Unifying patterns and template parts (areas or slots support for patterns and phasing out template parts)

Some initial notes:

Existing block rendering hooks for template parts (e.g., render_block_core/template-part) are in use in the wild. Any changes here needs to account for this. It's also possible to add block style variations to template parts at the moment, so this also needs to be accounted for.

More so than back-compat with phasing out template parts, we'd need to think through what problems theme authors are trying to solve and ensuring there is an alternative solution. For example, I regularly need to use the render_* hook for parts because we don't have a conditional system for rendering blocks.

@fabiankaegy
Copy link
Member

What about other entities (template parts, patterns, and styles) from themes?
Unifying patterns and template parts (areas or slots support for patterns and phasing out template parts)

Some initial notes:

Existing block rendering hooks for template parts (e.g., render_block_core/template-part) are in use in the wild. Any changes here needs to account for this. It's also possible to add block style variations to template parts at the moment, so this also needs to be accounted for.

More so than back-compat with phasing out template parts, we'd need to think through what problems theme authors are trying to solve and ensuring there is an alternative solution. For example, I regularly need to use the render_* hook for parts because we don't have a conditional system for rendering blocks.

I can attest that we are using both of these features heavily for template parts

@ellatrix
Copy link
Member

ellatrix commented Nov 22, 2024

The PR is ready: #67125

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Site Editor Related to the overarching Site Editor (formerly "full site editing") [Feature] Templates API Related to API powering block template functionality in the Site Editor [Feature] Themes Questions or issues with incorporating or styling blocks in a theme. [Type] Overview Comprehensive, high level view of an area of focus often with multiple tracking issues
Projects
None yet
Development

Successfully merging a pull request may close this issue.