Late last year I started working on an ongoing project that involved turning out a number of FSE (Full Site Editing)-based themes rather quickly from provided Figma designs.

(blockratize publishing)
Whatever is a programmer to do but make sure I’m being efficient and not reinventing the wheel by creating a solid starter theme.
Create Block Theme
When looking at Full Site Editing, probably the most useful tool to have on your belt is the Create Block Theme plugin. While you’re editing your theme in the Site Editor — customizing page templates, headers, footers, colors, typefaces — it then gives you a simple option to write your changes to disk in the theme itself.
Base for CBT
When you start using Create Block Theme, it gives you options to either make a child theme of your current theme, or (my preference) start from a clean, blank boilerplate theme.
For Create Block Theme, it’s this:
https://github.com/WordPress/create-block-theme/tree/trunk/assets/boilerplate
There’s really not a lot to it. A header and footer partial, a general index template, and a theme.json file that starts defining parameters. The idea is that you’ll start creating more templates and patterns in the Site Editor and then save them to the theme as needed.
Automatic namespacing with GitHub Actions
One of the things I was most delighted by building from my time on the Special Projects Team at Automattic was a GitHub Action we used when generating standard repositories from a given template repository. It was a project I built out at a team meetup in Dublin for template repositories.
Previously, some tooling was used on the command line to clone the scaffold repository into a local tmp directory and then do a local string/replace and finally push it back up to a new repository. This was relatively fragile, so this solution — handling the renamespacing — was a tremendous win.
For our use case here, though, it means that as soon as you use the boilerplate to create a new repository, with one click you can have the theme folder and all the namespaces reflecting the new instance’s name.
Build tools automation
Build tools used to be a nightmare to set up. With the coming of the @wordpress/scripts package, however, it became significantly simpler to configure and run.
However, there’s other tooling, such as generating translations, running PHP code formatting, and the like, that are best done in Composer instead. So, it’s nice when all your build tools are configured to work out of the box.
That’s why I’ve got my boilerplate leveraging a lot of the public work that the Special Projects Team built, and released for just this sort of utility.
Sass Support
When I need to write CSS, I prefer to write Sass. I find it easier to read, and easier to reuse.
However, with Block Themes, I find I’ve moved more toward (where possible) defining the styles in theme.json — as that means they can be overridden in the Site Editor down the road, without having to worry about conflicts of specificity and ordering to ensure our selectors are behaving as expected. Plus, they’ll automatically work better in the Block Editor for more of a WYSIWYG experience, from what I’ve seen.
Playground Support
Finally, another aspect that I wanted to configure when spinning up themes was supporting WordPress Playground functionality.
WordPress Playground is a packaging of WordPress in such a way that instead of connecting to a web server (or even having a web server), all the PHP server-side code runs in your browser directly. This is kind of fun as a thought experiment, but it took me a while to really grasp the utility of it:
It makes it trivial to set up a test site and let a user (or client or stakeholder) instantly test out a plugin or trial a theme.
That can mean that when getting feedback on a feature, you can just link the client directly to an up-to-date Playground being powered by the current state of your GitHub repository. And once most of the configuration is set up in the boilerplate, it’ll just work magically.
Populating with Starter Content
Anyone who has ever installed a theme and been instantly unimpressed can tell you what a let-down it is when every page is blank, and the site doesn’t look half as engaging as it did in screenshots.
Fortunately, Playground supports Blueprints, which give us several ways to load content in.
Firstly, it’s possible to bulk import content through a WXR (WordPress XML Export format) — there’s a step for blueprints where you can just give it the path to your export, and it will automatically pull it in.
But perhaps more interestingly, there’s a step called importThemeStarterContent instead — which gives us a lot closer to what we’re after. Starter Content is a feature that was introduced through the Customizer way back in WordPress 4.7 — nearly ten years ago. What a wonderful feature that just needs a little bit of love to bring it back up to scratching our itch here in the days of block-based themes, and it does the job quite well.
Starter Content Menus
When navigation block menus were introduced for Block Themes, there was a change from the prior implementation of nav menus (under the Appearance menu). For one, navigation block menus can trivially have other types of blocks contained in them, that couldn’t have been represented well in the classic nav menu post type — so it had to shift over.
The problem is that when theme starter content is imported, it imports as the pre-block nav menus. Core offers a class to rewrite them on demand to block-based menus, however, but they can’t be referenced directly.
So, instead, we can use another step to run some custom PHP when Playground is setting up the instance. Generally in the examples, it runs inline php, but there’s no reason we can’t just have it load a PHP bootstrap file from our theme instead!
{
"step": "runPHP",
"code": "<?php require '/wordpress/wp-load.php'; include_once get_theme_file_path('_playground/setup.php');"
}
Once that’s done, we just need to iterate through and tidy up after the Starter Content import (and maybe do a few other tiny things like configuring permalink structures)!
Finally, core’s navigation block only supports specifying menus by ID — no support for slugs. If we want to have distinct header and footer menus, then we can specify which goes where by adding a custom slug property in our template, that maps to the menu in our Starter Content — https://github.com/georgestephanis/theme-repo-template/pull/1
Is It Perfect?
No, of course not. But no project ever really is.
For me, though, it’s a great starting point, and has saved me a bunch of time for client work.
I hope you’ll find it useful, and make some super-cool-stuff with it.

Leave a comment