---
title: "Code Ouroboros: A WordPress / Eleventy Hybrid"
date: 2026-01-06T10:14:22Z
modified: 2026-01-06T10:19:43Z
permalink: "https://dgw.ltd/2026/01/06/code-ouroboros/"
type: post
status: publish
excerpt: ""
wpid: 717
categories:
  - Theme
featured_image: "https://dgw.ltd/wp-content/uploads/2026/01/Serpiente_alquimica.jpg"
featured_image_alt: Ouroboros drawing from a late medieval Byzantine Greek alchemical manuscript.
---

In a [previous post](https://dgw.ltd/2025/12/16/outatime/) I mentioned that, to properly test a calendar plugin, I needed a vanilla theme, something that would reflect a brand-new project. I could have used Twenty Twenty-Five, but where’s the fun in that?

I briefly considered an FSE theme, as I tend to do about twice a year. I even started building one and then… nope. I get it. It’s clearly a great pathway for a lot of people, and if I were going all-in on FSE I’d probably just use [Olllie pro](https://olliewp.com). But at the end of the day, I’m a developer. Building things in the UI just isn’t as much fun.

I need the smell of console errors in the morning. The flow state of writing CSS. The loop. My IDE.

Call it developer experience – whatever. I like the WordPress admin. I like writing in it and creating content, not building layouts. If you do, great. Go for it.

So, back to my comfy IDE and a custom hybrid theme. I’ve recently switched my daily driver from VS Code to [Nova](https://nova.app). I do use AI coding agents – specifically Claude Code, increasingly though, I don’t want that living too much _inside_ my editor, and VS Code is clearly going all-in on that direction.

Again, maybe this is “developer experience” (a term I have a few issues with – it feels a bit self-centred, although in the context of this post I’m being self-centred, so… meh). But I’m settling into being more present when writing code, with any AI interaction happening via the CLI / terminal ([iTerm2](https://iterm2.com)). IMHO, AI code completion removes too much consideration, a tab is just _too_ easy to press.

Obviously, I could have built something super simple using patterns I’ve refined over the years, namely [the theme](https://dgw.ltd/readme/) that drives this site. But I wanted to try something a little different, based on [some](https://dgw.ltd/2025/09/26/these-2-guys/) of the [experiments](https://dgw.ltd/2025/01/10/wp-scss/) I’ve been exploring on this blog.

[theme.json](https://developer.wordpress.org/themes/global-settings-and-styles/) is getting increasingly mature and has become the source of truth for design tokens on the sites I build. I also just straight-up love [Eleventy](https://www.11ty.dev), so in a brief mad-scientist moment I wondered: _could I create a WordPress / 11ty hybrid_ — taking the best of each, and enabling two pathways for publishing content?

So that’s what I did. Here’s the file structure:


```default
dgwltd-mvp/
├── src/
│   ├── 11ty/                    # Eleventy source files
│   │   ├── _config/             # 11ty plugins (filters, shortcodes)
│   │   ├── _data/               # Global data files
│   │   ├── _includes/           # Layouts and partials
│   │   └── content/             # Markdown/HTML content
│   ├── assets/
│   │   ├── fonts/               # Web fonts
│   │   ├── icons/               # SVG icons
│   │   ├── images/              # Source images
│   │   ├── scripts/             # JavaScript modules
│   │   └── scss/                # Sass stylesheets
│   └── utils/
│       └── utopia.ts            # Fluid typography utilities
├── build/                       # Webpack output (blocks)
├── dist/                        # 11ty output + compiled assets
├── scripts/                     # Build utilities
├── template-parts/              # WordPress template partials
├── eleventy.config.js           # 11ty configuration
├── esbuild.config.js            # Application scripts config
├── webpack.config.cjs           # Block editor config
├── theme.json                   # WordPress theme settings
├── functions.php                # WordPress theme functions
└── *.php                        # WordPress template files
```

We’ve got all the goodies:

- theme.json
- Block variations
- ES6 imports (e.g. [Alpine.js](https://alpinejs.dev))
- Minimal SCSS (with optional GOV Design System)
- Fluid typography via [Utopia](https://utopia.fyi/)

What really sets this apart is how the Eleventy build consumes theme.json to generate core styles and utilities. For example, WordPress automatically generates a spacing scale and inlines it in the <head> as:


```html
<style id='wp-block-library-inline-css'></style>
```

First, we consume the JSON in our Eleventy config:


```js
const themeJSON = JSON.parse(await readFile(new URL('./theme.json', import.meta.url)));
```

We can then use Eleventy to generate styles via things like:


```twig
{{ theme.settings.color.palette }}
{{ theme.settings.spacing.units }}
{{ theme.settings.typography.fontSizes }}
```

And even Tailwind-style spacing tokens:


```
```wp-block-code
.pt-{{ key }}-{{ subkey }} { padding-block-start: {{ subvalue }}; }
```

The great thing about Eleventy is that you can set the permalink to _any_ file type. So this file (wp.njk) has front matter as simple as:


```twig
---
permalink: '../src/assets/scss/wp.scss'
---
```

On the PHP side of the theme, this all “just works” out of the box. The Eleventy side, however, needs this declared in the base template:


```twig
{%- css %}
{#- main.css: Full theme styles #}
{% include "dist/css/main.css" %}
{#- wp.css: Design tokens from theme.json for static pages #}
{% include "dist/css/wp.css" %}
{% endcss %}
```

At this point we have parity between PHP and static site generation, with both consuming each other in different ways.

I now have two clear paths when developing a site. I can build content in the WordPress admin, export it all to Markdown (I have a plugin for that – another time, another post), drop it into the content folder with a data file, and boom: static site.

Create `{type}.11tydata.js` files:


```
```wp-block-code
// src/11ty/content/posts/post.11tydata.js
export default {
  tags: ["post"],           // Collection tag
  type: "post",             // WordPress post type
  status: "publish",        // Post status filter
  layout: "layouts/base.njk"
};
```

Or I can stay entirely in PHP land and just use Eleventy as the tail to generate some tasty utilities – fluid typography, spacing, service workers, offline pages, and so on.

Is this crazy? Probably.
Am I enjoying it? Massively.

Oh and I was able to test my plugin.