I’ve worked in agencies long enough to see every “solution” to the theme problem. Parent + child themes, universal base themes, custom functions shoved into the theme, even third-party builders like Elementor and Divi. I’ve tried them all.
And here’s the hard truth: the moment you put functionality into a theme, you’re setting yourself up for pain.
Themes aren’t built for that. They’re for presentation — branding, fonts, colors, layout. The second you start cramming functionality into them, you create fragile projects that break the moment a client wants a redesign, or worse, lock clients out of their own data.
That’s why I stopped building this way and moved everything into modular, self-contained plugins. It’s cleaner, more maintainable, and it finally lines up with what Gutenberg was designed to do from the start.
Trial and Error: Agency Lessons the Hard Way
Parent + child themes
For years, this was the standard advice. The parent held the “base logic” and the child theme overwrote only what was needed. On paper, it seemed clean and maintainable.
In practice, it was anything but. Every site had its own quirks, and the more projects you built, the more unique they became. Suddenly you were wrestling with the child theme instead of building the site itself.
When theme.json
came along, it made this worse. If you define something in the parent theme, it carried over into the child whether you wanted it or not. Sometimes you didn’t want that enforcement — but the parent-child relationship didn’t care. You ended up fighting with your own setup.
Base themes as a foundation
The next idea was a universal “base theme.” You’d start with a solid foundation and layer features on top as needed.
Sounds good, right? In theory, you’re supposed to strip away what you don’t want. But do you ever really? Most of the time, it just turns into a tangled mess. No way I’d touch it — especially if someone else was the one who put the code in to begin with.
So instead of a clean starting point, you end up with projects bloated by features you didn’t actually need, half-removed leftovers, and code that feels too risky to clean up. That’s not a foundation — that’s a liability.
Custom functions buried in themes
Another shortcut we used was putting custom functions directly in the theme. At first it felt fine — convenient, even. But then projects overlapped.
Suddenly you’re copying logic from one project to another, renaming functions that clash with client namespaces, untangling dependencies you forgot about, or trying to merge two different approaches into something “that just works.”
This was one of the biggest maintenance headaches I’ve ever seen in agencies. Old themes became fragile beasts no one wanted to touch. New hires couldn’t find where features lived. And everyone was afraid to delete old code because nobody knew what it touched anymore.
Third-party builders: Elementor, Divi, WPBakery, etc.
Then came the page builders. They promised a shortcut: less coding, more drag-and-drop. Clients loved the idea. Developers (at least at first) loved the speed.
But in reality, you ended up fighting their injected CSS, full of !important
rules. You were limited by the opinionated structures they forced on you. And when a client inevitably wanted something “just different enough,” it turned into a nightmare of overrides and hacks.
Worst of all: if a client ever wanted to migrate from one builder to another, you were starting over from scratch. None of it was reusable. Clients couldn’t understand why: “Isn’t it all WordPress?” No — not really.
My Gutenberg Mindset Shift
When Gutenberg arrived, it forced me to rethink everything. At first, I didn’t change much — I still put blocks in themes, I still leaned on must-use plugins. But the cracks kept showing.
Agency life is fast. And when you move fast, you cut corners. More than once, I saw a site completely crash just because someone switched themes. Why? Because our “must-use” plugin was referencing a theme function. Or we’d spin up a quick plugin to patch a client request, but it couldn’t run on its own — it depended on something else buried in the theme.
That’s when it clicked:
It doesn’t matter how clever your theme, plugin, or MU-plugin is. If the moment you switch themes your site breaks — or worse, your client loses ownership of their own data — all of that work is wasted.
That’s what I realized Gutenberg was really about. Its whole philosophy is separating presentation from functionality. Data should live in blocks and post types. Themes should only care about styling and branding.
From that point on, my approach changed completely:
- The theme handles look and feel — branding, fonts, colors, layout.
- The plugin carries the functionality. Each plugin is self-contained and doesn’t depend on a theme or another plugin.
- I stopped hard-coding typography or color rules in my blocks. Theme.json takes care of that.
Suddenly, things became modular. Switching themes didn’t break sites anymore. Content stayed intact. And I could finally see the real promise of Gutenberg: portable, structured data that outlives the theme it’s dressed in.
Building Modular Plugins Instead of Bloated Themes
These days, I spend more time refining plugins than I ever did tinkering with themes — and it’s the best investment I’ve made in my workflow.
I’ve organized everything into a system that’s both modular and scalable:
- Base functionality covers the essentials nearly every site needs.
- Premium functionality layers on advanced features when the project calls for it.
On top of that, I’ve built dedicated plugins for things like custom post types, each with their own blocks packaged in. For example: if a client needs testimonials, I activate the testimonial plugin. If they don’t? I don’t install it. No dead weight, no clutter.
That modular approach has completely changed the way I build. Instead of tangled themes and fragile workarounds, I now have a toolkit of solid, reusable blocks and post types I can trust. It makes my work faster, my sites more stable, and my clients happier.
But modularity isn’t just about where the logic lives — it’s also about where the styles live. Plugins should only provide enough CSS to define the skeleton: structure, layout, and accessibility. The moment a plugin starts forcing fonts, colors, or heavy design opinions, you’re back to fighting conflicts. Themes should always be in control of the presentation layer.
That balance is what makes the system work.
- Themes: design, branding, and visual expression.
- Plugins: structure, logic, and functional building blocks.
This isn’t just a workflow preference — it’s sound engineering. Separation of concerns. Modularity. Resilience. A clear boundary between presentation and functionality.
When you respect those boundaries, sites become predictable, portable, and maintainable. And that’s the kind of foundation you can actually trust.