WordPress block theme dev notes

Explore the anatomy of WordPress block themes and how they differ from traditional WordPress themes from a developer’s perspective.

In this post, I’ll explore the Twenty Twenty-Three (TT3) theme to learn the anatomy of a WordPress block theme from a developer’s perspective. If you want to get WordPress running and use the TT3 block theme, I have a post to help you here. I have been running the TT3 WordPress block theme for a couple of months now, and I am a big fan. It’s a minimalist theme out of the box, but it can be so much more with the full-site editor:

Twenty Twenty-Three default style

Let’s look at TT3 from a developer’s perspective to understand how block themes perform and their structural organization.

Block themes – It’s about the blocks

The WordPress site editor allows WordPress users to add, remove, and style blocks, patterns, and media using a JavaScript React powered GUI interface. In the screenshot below you can see how a user can add a block to the home page template:

Adding a block to the Twenty Twenty-Three (TT3) theme home page template

You can see there are quite a few blocks to choose from including:

  • Paragraph
  • Heading
  • List
  • Quote
  • Image
  • Gallery
  • Audio
  • Cover

So where do these blocks come from? Gutenberg, now integrated into WordPress, includes the library of core blocks. The core blocks are NOT packaged as part of the theme. If you want to look at a specific block’s source code, you can find it in the Gutenberg GitHub repo.

Themes can modify the appearance of existing blocks by registering styles but can’t add new ones. To develop and add custom blocks, you must integrate them as part of a plugin. If you could add blocks as a part of a theme, the block would break when the user switched themes. Click here to learn more about creating your custom blocks.

Twenty Twenty-Three (TT3) block theme network requests

This is a WordPress performance blog, so let’s take a look at the TT3 theme load performance. Out of the box, on a decent web host plan, TT3 will give a perfect 100-performance score on PageSpeed Insights. I opened my browser’s developer tools (F12), clicked the network tab, and used CTRL-F5 to reload the page. The network tab shows only a few assets requested:

Twenty Twenty-Three theme loading in the browser developer tools network tab

As you can see, the TT3 theme is quite a bit lighter than traditional, non-block WordPress themes. It weighs in at 27kB transferred over the network with gzip compression. Here’s a summary of what it loads:

lab.localThis is the HTML output from WordPress
This is the CSS for the navigation block (menu)
JavaScript for the Navigation block
JavaScript for responsive “hamburger” Navigation block
This is Twemoji from Twitter to standardize emojis ☘️ across systems.
http://lab.local/favicon.icoThis is the initial favicon request which results in a 302 redirect for a PNG file(next one down)
This is the site icon provided by WordPress

For comparison, the Twenty Seventeen theme from six years ago delivered 267kB across the network. The theme included a beautiful 115kB image of a potted plant on a desk, but the rest consisted of JQuery, JQuery components, and CSS files. Modern block themes no longer need these additional assets.

Can we make TT3 even lighter?

Navigation Block

You’ll note that three different files are needed for the navigation block in TT3, including quite a bit of JavaScript.

After a little investigation into the navigation block source code, I reached out to Ari Stathopoulos, a core WordPress developer. Ari directed me to a post he wrote in 2021, which explained that small block assets are sent in line with the HTML until they reach a 20KB limit. After the 20KB limit, assets are downloaded individually. You can change this using the “styles_inline_size_limit” filter. In the code example below, he shows how you can change the size limit to 50KB:

add_filter( 'styles_inline_size_limit', function() {
    return 50000; // Size in bytes.

Another alternative to reduce this clutter might be rebuilding the navigation block using pure CSS.

Emoji support script

The Twemoji script can go, please. Most systems support emojis without this script, and I am not fussy about how they look. Unfortunately, you need a plugin or custom theme to turn this off. ☹️


To eliminate the favicon 302 redirect request, you can add a site logo block in the site editor and enable it as your site icon in the block settings.

Where’s the CSS file?

You’ll notice something missing from the network requests… there is no separate style.css download. We saw a request for the navigation CSS but where’s the rest? Traditional WordPress themes required a style.css file containing the page CSS and the theme metadata including the title, description, author, etc.

WordPress block themes also require a style.css file, but the Twenty Twenty-Three theme doesn’t link it in the HTML. If you view the source on the returned HTML, you will notice the following:

  • WordPress packs much of the CSS inline in the head element.
  • The CSS is modular – In the example below, you can see a CSS section for each block type, including a descriptive ID attribute.
  • WordPress limits the CSS to only the blocks used on the page.
<style id='wp-block-post-excerpt-inline-css'>
<style id='wp-block-post-date-inline-css'>
    .wp-block-post-date{box-sizing:border-box} ...truncated...
<style id='wp-block-spacer-inline-css'>
<style id='wp-block-post-template-inline-css'>

This is a highly performant way to load a page because the browser doesn’t have to stop and make a separate request to get the CSS file. Additionally, WordPress loads much of the CSS inline in the HTML head element, resulting in minimal un-styled content. I approve. 😉

What’s this? SVG in WordPress block themes?

I am a big fan of SVG files. They are a great way to add responsive visuals to your website. Unfortunately, WordPress doesn’t support SVG in the media library for security reasons. I have to install a plugin to get my SVG support, which makes me sad.

Do you know that little hamburger menu websites display on a mobile device to access their menu? Imagine my surprise to see an SVG tag in the navigation block to render it. Come on, WordPress, can’t you let everyone in on the fun?

As I started looking around, I noticed WordPress uses SVG in a number of places. If you want to use SVG files in the media library on your WordPress site, the Safe SVG plugin works very well.

JavaScript Placement

I discovered that the Twitter emoji JavaScript library and the navigation block library are linked in the document’s head. I assume they did this to ensure the early rendering of emojis and the navigation menu, avoiding any content shifting during the page load. I prefer placing JavaScript at the end of my HTML to prevent it from blocking the page rendering.

Skip links

I found some JavaScript towards the end of the HTML to generate a “skip link.” Skip links are an accessibility feature to allow screen reader users to skip tabbing through all the header elements at the top of the page, I.e., the navigation bar, and jump right to the content. You can learn more about skip links on the Make.WordPress.org site.

I looked at the WordPress source, and all block themes get the skip link JavaScript in the footer by default. Why can’t we create the page skip link server-side while rendering the page?

Lean, Semantic HTML

The Twenty Twenty-Three theme home page HTML output is relatively lean once you get past all the JavaScript and CSS in the head element. The body is only about 60 lines of HTML. This will grow as you add more posts but isn’t nice to start off with something so lean?

The Twenty Twenty-Three theme uses semantic HTML tags appropriately and scored well on accessibility tests. Here are some examples:

  • The header is in a header element.
  • The menu uses the nav element.
  • The main page content is inside a “main” element.
  • List items using the ul/li tags.
  • Footer content is inside a footer element.

These may seem like obvious choices, but I have many legacy themes that used generic div tags for everything.

Overall, the HTML appears lean, well-crafted, and well-thought-out. The organization remains consistent even when you add blocks to the page using the site editor. If early GUI page editors produced horrifying HTML that shocked you or if you struggled with exporting HTML from a Word document, the WordPress block theme output will pleasantly surprise you.

WordPress block theme files and folders

Let’s take a look at the Twenty Twenty-Three theme files and folders. I am using Local to run a local copy of WordPress so the path to the Twenty Twenty-Three theme folder is “…\Local Sites\lab\app\public\wp-content\themes\twentytwentythree.”

Here’s what you will find:

  • 📁assets
    • 📁fonts
      • 📁dm-sans
      • 📁ibm-plex-mono
      • 📁inter
      • 📁source-serif-pro
  • 📁parts
    • 📄comments.html
    • 📄footer.html
    • 📄header.html
    • 📄post-meta.html
  • 📁patterns
    • 📄call-to-action.php
    • 📄footer-default.php
    • 📄hidden-404.php
    • 📄hidden-comments.php
    • 📄hidden-no-results.php
    • 📄post-meta.php
  • 📁styles
    • 📄aubergine.json
    • 📄block-out.json
    • 📄canary.json
    • 📄electric.json
    • 📄grapes.json
    • 📄marigold.json
    • 📄pilgrimage.json
    • 📄pitch.json
    • 📄sherbet.json
    • 📄whisper.json
  • 📁templates
    • 📄404.html
    • 📄archive.html
    • 📄blank.html
    • 📄blog-alternatives.html
    • 📄home.html
    • 📄index.html *
    • 📄page.html
    • 📄search.html
    • 📄single.html
  • 📄readme.txt
  • 📄screenshot.png
  • 📄style.css *
  • 📄theme.json

* style.css and templates/index.html are the only files necessary in a theme.

assets/fonts folders

The assets folder only has a fonts folder. I suspect if you built a theme with images, they would live in an images folder under assets.

The fonts folder is self-explanatory. TT3 includes four font folders for each of the four typefaces (not including the system font option). Each folder contains the font files in WOFF2 format and a text file containing the license information. The fonts included in TT3 are all licensed under the SIL Open Font License.

The included Source Serif Pro and Inter font files are giant, and I don’t know why you would want to use them. Perhaps they contain more glyphs for international use. The inter font weighs in at 785KB! I added a lighter-weight serif font to use in the FireflyWP theme headers.

parts folder

The parts folder stores HTML template parts like “header.html,” which the theme uses across multiple pages. More on templates when we get to the templates folder.

patterns folder

Block patterns are like mini themes of pre-arranged blocks you can add to a page and customize. Let’s say you have a formula for a great product landing page with excellent conversion rates. It might include a headline, product description, an intro video, and a call to action button. Instead of recreating this formula and placement on all your landing pages across all your websites, you could build a reusable block pattern to insert and update where ever you need it.

The TT3 theme contains block patterns for a call-to-action, footer, comments, and others. If you open one of these block pattern files, you will find HTML with “block markup.” I’ll go into more detail on this later in the templates section.


The styles folder contains preset theme styles encode in JSON. There is a JSON file in the style folder for each style variation displayed under “Browse styles” in the global styles section of the WordPress site editor.

Style options in the site editor
TT3 styles folder file list

templates folder

The templates folder contains an HTML template for each type of WordPress page. I.e., the home page, single post, single page, and search page. The HTML template files effectively replace the PHP files used in legacy themes.

Specially formatted HTML comments, known as block markups, instruct WordPress on which blocks and style modifications to include in the HTML output. Here is a snippet from the TT3 home.html template file to give you an idea what this looks like:

<!-- wp:template-part {"slug":"header","tagName":"header"} /-->

<!-- wp:group {"tagName":"main",...truncated...-->
<main class="wp-block-group" ...truncated...>
<!-- wp:heading {"level":1, ...truncated...-->
<h1 class="alignwide" ...truncated...>Mindblown: a blog about philosophy.</h1>
<!-- /wp:heading -->

Look at the first line containing “template-part.” This is pulling in the header template part in the “parts” folder. Since the header template part is utilized across multiple pages, the same line repeats in other template files.


The theme readme.txt file has similar content to the theme metadata in the style.css file, including the theme name and description. It also has a change log.


The screenshot.png file is exactly that, a screenshot of the theme that shows up in the themes directory.


There is a style.css file in the root of the theme folder, but it doesn’t have any CSS. It only has the theme metadata (name, description, author, etc.). The CSS is all loaded into the HTML head by WordPress. You could put style information here, but I think it is more appropriate to put it in the theme.json file.


Theme.json is new to block themes and is a central component of your theme. It defines your theme’s style, layout, and site editor options. WordPress block styles are defined by WordPress core, user changes, and the theme itself. The theme.json file manages these styles, ensuring that only the most relevant ones are enqueued.

The TT3 theme.json file has the following structure:

  • Schema and version
  • Custom Templates
    • Blank
    • Blog (Alternative)
    • 404
  • Settings
    • Default color palettes
    • Layout properties include content width and “wide size”
    • Spacing – The TT3 theme uses clamp, rem, and vw to manage spacing
    • Typography including family, stretch, style, weight, size, and the src path in /assets/fonts
  • Styles
    • Blocks (I.e., core/naviagation, core/post-author, core/post-content, etc.)
    • Color (background and text defined using CSS custom properties/variables)
    • Elements (I.e., button, h1…h6, link)
  • Template Parts
    • I.e., header, footer, comments, post-metadata

Where and how WordPress site editor changes are stored

When you make changes to a WordPress block theme in the full site editor, and click “Save”, WordPress stores your changes in the the WordPress database (usually MySQL). The theme files remain untouched.

Each time you save changes to your theme, a new revision is written to the database. The part of the template you change is saved to the wp_posts table in the database. If you change the theme colors for example, it saves the block of JSON for the theme styles that includes the colors. If you add a social media icon to the home page layout it will save a snippet of that template with your change versus the entire theme.

In the MySQL Workbench screenshot below you can see the new rows created in the wp_posts table as I saved my changes in the site editor.

Screenshot of the wp_posts table after save changes in the WordPress site editor

Building themes using the site editor export

The site editor boasts an outstanding Export feature that merges all your site editor changes from the database into the current theme and saves them as a new zipped theme package. This feature enables non-developers to create and distribute custom themes, further democratizing theme development while delivering excellent page load performance.

WordPress theme export feature

What’s next?

At this point, you should have a basic understanding of the Twenty Twenty-Three WordPress block theme structure. In a future post, I’ll cover creating a new theme from scratch.



, ,




Leave a Reply

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