The theme was sixty-one PHP files in 2023, when the site editor migration started. Three years later it is six block templates, four parts, seventeen patterns, forty lines of functions.php and fourteen hundred lines of CSS — and nothing has gone wrong, which is why it was worth counting.
The symptom
there is no symptom. this is an audit of a decision
nobody has revisited since it was made.
the question that prompted it: the ratio of theme code
to plugin code has inverted since 2023 and nobody had
noticed.
2023 theme 8,100 lines plugins 4,200
2026 theme 2,000 plugins 11,400
which is either a good boundary or a migration that
went past where it should have stopped.Why it happens
A theme accumulates functionality because it is the file you edit, and a migration to block templates removes the place to put it. Everything that could not be expressed as markup had to go somewhere, and the somewhere was a plugin.
The fix
What is left
templates/ 6 index, single, page, archive, 404,
search
parts/ 4 header, footer, sidebar, post-meta
patterns/ 17 campaign layouts, page sections
styles/ 2 the default and one variation
*.php 2 the two with conditional queries
functions.php 40 lines
assets/css 1,400 lines
total about 2,000 lines, against roughly 8,100 in 2023.What moved into plugins, and whether that was right
custom post types → a plugin. they survive a theme
switch, which is the argument.
shortcodes → blocks, in a plugin
REST endpoints → a plugin
image sizes → a plugin, non-obviously: the
images outlive the theme
the settings screen → deleted
a taxonomy → a plugin
the breadcrumb → a plugin, and arguable: it is
presentation, and two plugins'
templates use it as well
the rule: anything that should survive a theme switch
is not the theme's.A custom post type registered by a theme is content that disappears when somebody changes the design, which is a bug waiting for a redesign and is what most WordPress themes do. Applying the survive-a-theme-switch test to every function removed almost everything, and the breadcrumb is the one case where the answer is genuinely unclear.
The forty lines
add_action( 'after_setup_theme', function () {
add_theme_support( 'wp-block-styles' );
add_theme_support( 'editor-styles' );
add_editor_style( 'assets/css/editor.css' );
} );
add_action( 'wp_enqueue_scripts', function () {
wp_enqueue_style( 'turkerdev',
get_theme_file_uri( 'assets/css/main.css' ),
array(), turkerdev_asset_version( 'main.css' ) );
} );
remove_theme_support( 'core-block-patterns' );
Removing core’s pattern library is the line that matters most for how the site is edited — with it enabled the inserter offers dozens of patterns styled for a different theme, which teaches an editor that patterns produce things that do not match the site.
The two PHP templates
the rule, which has held for three years: if the
template contains a conditional that changes WHAT IS
QUERIED, it stays PHP.
page-pricing.php renders a table from a
third-party API, with a cache,
a fallback and error handling.
the query block cannot express
"call this service".
→ could be a dynamic block.
costed at three days against
a template nobody edits.
archive-event.php orders by a meta value, with a
different ordering for past
events. a pre_get_posts filter
plus a block template was tried
and the conditional ordering
did not survive.
conditionals affecting presentation are fine.Editors changing things
developer tickets for layout or copy:
2023 (pre-migration) 41
2024 19
2025 8
2026 (to date) 2
changes editors made themselves, which was zero
before:
template part edits 64
pattern insertions 188
style variation
switches 3
sixty-four template part edits are sixty-four deploys
that did not happen.Forty-one tickets a year becoming two is the return on the 2023 migration measured three years later, and it is the only number that ever mattered. The three style variation switches are the surprising one — a feature that was expected to be used constantly and is used quarterly.
What broke along the way
2023 two rendering regressions found by a markup
diff, both invisible visually
2024 a font installed by an editor without a
licence check, before the collection was
restricted
2024 a plugin update that changed a hook's
arguments, silently
2025 a pattern detached on nine pages, discovered
by a monthly query
2025 speculative loading prefetching a basket
removal link, which is a 2019 anti-pattern
that became a bug
2026 nothing yet
six incidents in three years, none of them an outage.Verifying it worked
$ ./bin/render-diff --urls=urls.txt --against=2023-08
188 URLs compared
identical: 171
differing: 17 (all intentional design changes)
$ find . -name '*.php' -not -path './node_modules/*' | wc -l
3 # functions.php and the two templates
$ wc -l assets/css/main.css
1,412
$ ./bin/editor-changes --since=2023-08 --by-year
2023 4 2024 38 2025 121 2026 92
$ npx backstop test
Passed: 44 Failed: 0The rendered markup for a hundred and eighty-eight URLs still comparable against a 2023 baseline is what makes an audit like this possible three years later, and the seventeen differences are all deliberate. Editor changes rising every year is the trend the migration was for.
What this costs
A site whose appearance lives in two places, still. A template part edited in the site editor is a post in the database, so the git version is a default rather than the truth — and a staging-to-production content migration now moves appearance as well as content, which the previous arrangement kept cleanly separated.
The theme is also now so thin that the boundary with the plugins is doing all the work, and that boundary is a convention rather than a mechanism. Nothing stops the next person putting a custom post type back in functions.php, and the only reason it has not happened is that the file is forty lines and obviously has a shape.