,

Dev Considerations for a New FSE Project

I’m kicking off another larger/quasi-enterprise website build and am planning on going full steam on a block-based theme again. My plan with this post is to outline the main developer experience issues I know that I’ll be facing, with some thoughts around how I plan to solve them, including what tools I might need to leverage along the way. This post is sort of an update to an earlier post: Thoughts on Version Control for Block Themes.

Typically at the beginning of a project, we’ll outline the technical specs, like what custom features, post types, integrations, blocks, etc we might need. This is just focused on full site editing developer workflows. In the era of classic themes, you could really build an amazing and lean WordPress site with just ACF and a good starter theme. With FSE, it’s a lot harder to resist the urge to add low-install-count plugins or just give up and use a page builder. Hopefully more open discussions like this will help us solve these issues.

If you’re building similar block-based sites, please connect with me so we can share resources. There’s a group you can join in the Make WordPress Slack #outreach channel along with a few GitHub discussions, including this one on Version Control.

Base Theme & Assets

I have a starter FSE theme that a colleague and I have been working on that is pretty great to work with. The key differentiator is that the theme is for developers with a build process built on top of @wordpress/scripts.

It also includes scaffolds for adding custom settings to the block editor, custom blocks, core block extensions, and selectively enqueueing block-specific stylesheets without having to write almost any extra code. As much as possible it relies on using theme.json and the corresponding CSS variables when CSS is needed.

The theme itself is completely un-opinionated in terms of design (this is not a starter theme like Ollie or Rockbase) and is sort of like the _s for full site editing. There’s a bit of real-world testing that’s needed, so happy to take it for another test drive.

Frontend JavaScript Framework

I like having a bit of structure for my frontend JavaScript, especially when building custom interactive blocks like tabs or carousels. I don’t want to go back to jQuery but it’s really nice having some basic structure. Last time around Alpine.js was perfect for that. Having experimented a bit with the Interactivity API recently (which has a similar approach of custom directives mixed into your HTML), I think that could be a fun way to go.

This will work if I don’t need anything complicated, like custom stores for example. The way it uses JavaScript Modules means it won’t work with the current build process (commands require the --experimental-modules flag currently, which then seems to break our custom webpack config for multiple entrypoints).

If I need to write actual JavaScript for it, I guess I could write it outside the build step or just make any interactive blocks in a separate plugin directory.

Templates & Template Parts

This is where we move into one of three major workflow gaps in block themes, starting with – how do I control the design of the site once content has been entered in? Templates/template parts can be easier, assuming nothing needs to be edited on the live site. Meaning you can completely version control them if you make a few modifications:

  • Templates (i.e. single, archive) can be exported from the site editor to the theme using Create Block Theme. As long as the templates are never touched on the production site, changes can be pushed from local to prod pretty easily. No editing your 404 page or archive templates on prod!
  • Template Parts (i.e. header, footer) can also be exported, but its worth noting that CBT converts them to Patterns first (which does allow them to be stored as PHP with image assets added to the theme by default). But then the minute they’re edited on the production site, they “break” the connection to the pattern.

I’m not really worried about templates as my strategy is basically to hide the entire site editor from the client. That said, I miss the concept of “Block Template Parts” from hybrid themes – it was an easy way to curate a couple block editor “chunks” without opening up the entire site editor. (I might consider doing something with a CPT if I need to give them access to alter any content that’s inside a template, say a Blog hero area).

The template parts (in this case, the header and footer) can probably remain untouched by the client. The only piece they’d need to modify might be menus or the social icons. There’s also a few links inside them (i.e. Privacy Policy, Terms of Service) so maybe those can be menus as well. I’ll talk about my solution for menus below.

For social icons, if they actually need to be able to edit these, I can control them with a reusable block or a filter. That said, that’s a low priority.

Synced Patterns/Overrides

I’m treating patterns as a completely separate topic from templates: Block Patterns are not exported into your theme by CBT. There’s always Pattern Manager, but it’s abandoned and has been slowly falling apart with each new core release (the inability to easily group blocks just kills me).

The big tradeoff is always: how can I control some elements of a pattern’s design in the code (say spacing and overall layout) but other parts (content, colors) per instance?

The end goal would be partially-synced patterns/pattern overrides, but not only is that not ready for 6.5, I have serious doubts that an ideal user experience will get fully realized in the next year when ideas like forcing users to type into text input fields in the sidebar to edit their page content are being considered. And there’s a lot of underlying work that needs more thought.

Potential approaches to patterns

Add a class to a pattern’s outer element – then you just override things with CSS. The downside is the styles you see in the inspector controls might be wrong. That said, I think this is probably one of the quickest/most common approaches I see.

I could use ACF Blocks in place of patterns, but then that starts to remove a lot of the benefit of the block editor and you’re constantly making trade-offs. ACF Blocks are really useful at the block level, but not at the larger ‘pattern’ level, and editing input fields in the sidebar or a form is sort of a ‘last resort’ approach.

Custom dynamic blocks are comparable to the ACF Blocks approach – helpful at the individual block level. A good example of this might be Rich Tabor’s Cards block. Sure you could build this with core blocks, but Rich makes a good point that this stripped down dynamic block is a cleaner user experience. I’ll probably have a few of these for elements like icon lists and cards, but they don’t solve the larger pattern issue.

Patterns with contentOnly Locking

The approach I’m leaning towards is using block patterns but setting contentOnly locking to them. The structure would essentially be an outer group block where you can override the background/text color and overall spacing. Then inside that another group block with the contentOnly locking enabled- then the rest of the pattern is inside, where you’ll only be able to edit text, images, buttons, etc.

I’ve created a variation of the group block to scaffold this structure that essentially looks like this:

{
name: "content-locked",
title: "Content Locked",
description: "Group block with locked content",
attributes: {
align: "full",
tagName: "section",
className: "pattern--",
layout: { type: "constrained" },
metadata: { name: "Pattern" },
},
innerBlocks: [
[
"core/group",
{ templateLock: "contentOnly" },
[["core/paragraph", { placeholder: "Content locked" }]],
],
],
},

With this variation, there’s now a “Content Locked” template I can insert that has everything I need to scaffold a block pattern.

The contentOnly locking works well enough. You can’t edit anything but text/images and you can’t even select blocks that aren’t editable, so all the groups and columns sort of disappear. Users can also leave content or images empty and for the most part, those blocks won’t show up on the front end.

Where it breaks down is the idea of repeatable inner blocks. For example, once locked, you can’t add more buttons to a buttons block or more list items to a list block. You can’t take a three-column or grid layout and duplicate or remove columns. In that sense it harkens back to the ACF Flexible Content days – way too rigid. For a few of my designs, I might actually need to make small custom blocks to work in this mode.

That balance between flexibility and stability is essentially the hard problem the core team will need to solve. And I guess for power users, you can actually just “unlock” a contentOnly locked block in the block editor and edit anything anyway (yep).

The downside of all this is that it doesn’t really solve version control and global updates to the attributes of blocks inside the pattern. For example – if I add a default amount of spacing or color on a block but want to change it globally, I would need just hard-code some CSS over it. But… I don’t really see another option without pattern overrides in core. And because of the nature of patterns, this CSS will have to be loaded globally (although I do have an idea for better block styles management…).

For now, block patterns are really serving as wireframes, and as long as the structure is solid I can tweak the rest later. The end user doesn’t see any settings on those innerblocks, so they don’t notice/care if I’m overriding it with CSS.

Patterns in Themes

The last piece is getting block patterns from WordPress into your theme for version control. And then still being able to edit a pattern in the site editor once it’s saved in your theme. Obviously those were the exact two use cases that Pattern Manager excelled at. The goal would be for Create Block Theme to solve this problem, maybe by looking at Pattern Manager and taking what works.

In the meantime maybe the best option is to just keep using Pattern Manager. If I had extra time, I could fork Pattern Manager and at least fix the “grouping” issue and any other major problems.

(I did do some experiments with a custom “Pattern” block that would automate some of this contentOnly locking work and pull the patterns directly from your theme, but I ended up just getting too deep in the weeds on it and it felt too fragile an approach.)

Responsive Design

Responsive design in the block editor is rough. In the past, I’ve included custom block-level responsive design controls in projects as a way to get around this. An example is adding a small “Reverse on Mobile” checkbox to Columns or Row blocks.

If I end up going the approach above of tightly controlling all of my patterns anyway, then I’m less worried about responsive design, because I can just code it in with CSS. I’m not even sure I’ll need to add any custom settings, though a “center text on mobile” checkbox will probably end up making it in.

That said, this design really has no negative margins, no crazy mobile stuff. I’m getting lucky that the “intrinsic” design approach will mostly be fine here.

Except of course for… the mega menu.

Nobody’s best friend. The navigation block. Where do we start?

To me, the lack of support for menu “locations” in the core Navigation block is a criminal offense. It essentially means that any templates / template parts with menus in them cannot be version controlled at all. This is… unacceptable? How many headers and footers don’t have any navigation menus in them? It also makes switching themes much more tedious than it needs to be.

To make matters worse, the header design I have is basically ‘mega menu’ territory.

For the footer and top-header menus, I was going to try Jonny Harris’s Classic Menu Block. Unfortunately, it doesn’t solve the one issue I want it to solve – fetch a menu by its location, not an ID via the database. So… I’m probably just going to fork his plugin and see if we can store the menu location instead of the menu itself. Looks doable. And maybe add in block style for some horizontal menus.

For the header, I’m going to try something similar to Nick Diego’s concept of a mega menu block, but potentially with a bit of the complexity stripped out, mainly because my users will never need to edit it. Each dropdown in the mega menu will be a block template part made up with Classic Menu Blocks. My clients will probably be editing classic menus for everything, with pretty much no control over the design.

So… no navigation block if I can help it.

Conclusion

There’s plenty of other decisions that go into building a site like this. A few quick examples from this project:

  • theme.json and reminding myself how to style basic elements like the separator and bullet lists.
  • the use of SVG Icons and a custom add-on plugin I had to build for Nick Diego’s The Icon Block.
  • the unique hosting/deployment situation.
  • a Salesforce integration and the ability to personalize content based on referral info.
  • and then of course the client, with their deadlines and bureaucracy and other incentives.

There was a solid decade of agency life where a lot of these workflow questions were answered, where there were best practices and courses and tutorials and major theme frameworks dedicated to solving these issues. And there are still plenty of other options (like Sage or TailPress) that are pushing the boundaries of modern WordPress in completely different ways.

I would love to just build a website on core WordPress, offer a solid visual editing experience, and not break my brain trying to figure out how to control everything in a nice git repo. I’m making progress with each project- with help from other community members sharing their ideas- and hoping that after this build I’ll have a few more answers, and that core will have made a few more steps towards offering a decent developer experience. I’m hoping that thinking aloud like this helps.

To repeat what I said above: If you’re building similar block-based sites, please connect with me so we can share resources. Let me know if you see any holes in my strategy or want to point me towards anything else useful.

8 responses to “Dev Considerations for a New FSE Project”

  1. António Carreira Avatar
    António Carreira

    I’m developing FSE websites for my clients for the past year or so, and this article sums up all my pain points so far.
    I’ve recently submitted a plugin to the WordPress repository that allows you to add a menu ID or a menu location to a block. Still waiting for approval, but I’d love to have your opinion if you’d like to try it out.

    Regarding responsive stuff and small issues with FSE design, I use a few custom auxiliary classes and that fixes most of the issues for me.
    No auxiliary classes on the content side, though. Clients and auxiliary classes don’t match. 🙂

    1. Brian Coords Avatar
      Brian Coords

      Send it to me! I’d love to try it. I ended up forking the Classic Menu Block plugin and getting it to work with locations in the meantime.

      Yeah I’m thinking about automating Patterns w/ classes for now so that I can always be ready to override the styles myself. Maybe.

  2. Carsten Avatar

    Hello Brian,

    following on, that your last YouTube video feels directly related to my current work, I wanted to let you know, that I had some kind of similar problems to solve, while adding some Interactivity to a block-variation.

    I probably ran into the same issue regarding the wp-scripts build-process with multiple endpoints, while using the —experimental-module flag. Asking on slack hasn’t revealed any easy answer, yet.
    See here https://wordpress.slack.com/archives/C02QB2JS7/p1710679715908639

    Maybe you know if there is an open issue about this, or where to best place feedback?!

    1. Brian Coords Avatar
      Brian Coords

      Because its still behind an ‘experimental’ flag, I’m not too worried about it all working _eventually_. In the meantime, the best approach is probably to do anything with the Interactivity API in a separate plugin and then merging it later. Not a great answer but until they remove the ‘experimental’ flag it’s safe to assume that it could change anyway.

  3. Trevor Robertson Avatar

    I was just reviewing the latest Gutenberg Times post and read about this new plugin (Pattern Editor – https://wordpress.org/plugins/pattern-editor/) and it made me think back to this very handy article you wrote. Pattern Editor could be a potential option to replace Pattern Manager — at least until this functionality is in core which would be the ideal situation I think.

    1. Brian Coords Avatar
      Brian Coords

      Thanks! Someone pointed me towards this on Twitter and it’s on my list to test this week as I build out some new patterns.

  4. Trevor Robertson Avatar

    Hey Brian, I was just re-reading this post, and now I’m back with another plugin suggestion for you! Classic Menu in Navigation Block – https://wordpress.org/plugins/classic-menu-in-navigation-block/ – might help for solving the lack of Menu Location thing in Classic Menu Block? Hopefully!

    Also, just to clarify, in the Navigation Block section of your post, you mentioned you’d be using a “block template part”, but this being a FSE theme, you are just using “Template Parts” right? I thought the former was only for hybrid themes?

    Either way, thanks again for this post! I’ve been slowly working through all the same things the past year, so it felt good to read this. And indeed, navigation, ugh, days lost to trying to solve that puzzle…

    1. Brian Coords Avatar
      Brian Coords

      Hey thanks for sharing. So the way I solved the navigation (for now) was to use Jonny Harris’s Classic Menu Block plugin. The downside was that it still wanted you to pick a specific menu from your site, so I did have to fork it to get it to use menu “locations” not individual menus. It looks like the one you’re sharing does that out of the box, so I’ll definitely check it out.

      And yes you’re right – I am referring to a “template part” not a “block template part” ‍♂️

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.