With each release, WordPress is giving more and more power to the theme.json file. The future of WordPress theme development may largely skip CSS with most developer styling hours focusing on this file.
Overall, using this super-powered config file has a ton of benefits, but one of the downsides is that JSON is not the best to work with. A typical theme.json file is quite long and easy to get lost in, particularly when you start styling specific blocks and element hover states and it starts to look like this (direct from WordPress docs):
{
"styles": {
"blocks": {
"core/group": {
"elements": {
"h2": {
"typography": {
"fontSize": "var(--wp--preset--font-size--small)"
}
},
"h3": {
"typography": {
"fontSize": "var(--wp--preset--font-size--smaller)"
}
}
}
}
}
}
}
This brings back memories of callback hell, before async/await in javascript, and is really not pleasant to try to navigate.
A solution is to break this file up into components, so that it is easier to focus on specific sections without getting lost in one huge super-file.
Side note: if you are new to theme.json, I have an intro to theme.json post that covers the basics.
Splitting the code
In order to do this we will set up our configuration in javascript files instead of JSON, so that we can treat separate sections as modules, then import and combine them, and finally write the result to the theme.json file our WordPress install will use.
This has the added benefit that we are able to add javascript comments and even logic to our config! This is something JSON alone does not allow.
First, in our theme directory we will make a new directory and call it theme-json. This is where we will store all our pieces that will form the final theme.json file. You can see an example of what it will look like below:
For the purposes of this tutorial we’ll split our file into settings, styles, and config (which covers anything not in the settings/styles section), but you could split this a lot more if it suits you!
In each of these files we will just export an object that corresponds to the data we would normally put within the given section of a typical theme.json file:
You might have noticed in the previous image there is also a compile.js file. This will contain the script to actually combine everything.
Within this file we’ll import the others and shape it into one object that mirrors the theme.json structure. Then we’ll use json.stringify and write the file into the main directory:
import settings from "./settings.js";
import styles from "./styles.js";
import config from "./config.js";
import * as fs from 'fs';
const theme = {
...config,
settings: settings,
styles: styles
}
const json = JSON.stringify(theme)
fs.writeFileSync('theme.json', json)
At this point, we just have to do some setup with node scripts.
If your theme does not already have a package.json go ahead and run npm init -y
.
Then within the theme.json set "type": "module"
. This allows us to use the ES6 style imports you see above in our compile script when it is run via command line.
Finally, we can add a command to actually run the compile script. The finished package.json will look like this:
{
"name": "example",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"json-theme": "node theme-json/compile.js",
},
"keywords": [],
"author": "",
"license": "ISC",
}
Now in the terminal we can run npm run json-theme
and it will generate our final theme.json file!
Watch and Generate Theme.json in the Background
This works, but wouldn’t it be nice if we didn’t have to run this anytime we changed something in the source javascript files?
No problem.
All we have to do is add a package called nodemon:
npm i --save-dev nodemon
Then we add one more script to our package.json:
"scripts": {
"json-theme": "node theme-json/compile.js",
"watch-json-theme": "nodemon --watch theme-json theme-json/compile.js"
},
Now we can run this new script with npm run watch-theme-json
and just leave it in the background and anytime we change any values in our source javascript files it will go ahead and recompile and generate your theme.json file!
Wrap Up
Personally, I hope that in the future WordPress switches to a theme.config.js or something to that effect instead of a JSON file, but in the meantime I hope this helps others who find that the theme.json file can get a bit unwieldy.
I like to have my styles.js and settings.js open side-by-side, so that I can easily reference the variable names and custom values I set up, while styling various blocks and elements:
Another great add on to this would be some validation in the compilation process. You could for instance add a section to the configuration file that checks the structure of the “theme” object before converting it to JSON and warns you about any potential issues.