From WordPress Frustration to a Clean Architecture: The WebifyCMS Pivot #1
WebifyCMS Admin
announced in
Announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
From WordPress Frustration to a Clean Architecture: The WebifyCMS Pivot
June 2026 — Mohammed Shifreen, Founder
How It Started
WebifyCMS was not born from a product roadmap. It was born from frustration.
Like thousands of PHP developers, I built on WordPress. And like many of them, I hit the same wall — a codebase where extending anything meaningful meant wrestling with hooks, filters, and global state. The moment a project grew beyond a simple information site, WordPress stopped feeling like a platform and started feeling like a constraint. Custom requirements that should have taken hours took days. Business logic was scattered across plugins, themes, and action callbacks with no clear ownership.
The obvious answer was to build something better. Something I could extend cleanly, own completely, and grow alongside real requirements. That decision is what became WebifyCMS.
The First Foundation: Yii2
The earliest version of WebifyCMS was built on Yii2. At the time, it was the right call — it was the framework I knew deeply, it was performant, and it had a sensible enough structure to get something working quickly.
But as the project grew and my understanding of software architecture deepened, a tension emerged. Yii2's conventions and WebifyCMS's ambitions were pulling in opposite directions. The framework's Active Record pattern, its tightly coupled components, and the difficulty of writing truly testable, framework-agnostic business logic made it increasingly clear that building a serious CMS platform on top of it would create the same kind of structural debt that drove me away from WordPress.
The infrastructure was getting in the way of the architecture.
The Research Phase
Rather than bolt a new design onto an existing foundation, I paused and did the work properly. Several months of research into software architecture — Domain-Driven Design, Clean Architecture, bounded contexts, aggregate roots, domain events, and the ports-and-adapters pattern — gradually clarified what WebifyCMS actually needed to be.
The core insight was simple but consequential: the business logic of a CMS should have no dependency on the framework delivering it. A
Postaggregate should not know whether it lives in a Yii2 controller, a Laravel endpoint or a CLI command. AnEmailvalue object should validate itself without importing anything fromyii\base. The domain should be pure PHP — testable, portable, honest.This is what Clean Architecture with DDD provides. The framework becomes infrastructure. The business logic becomes sovereign.
What Is Being Archived
The Yii2-based repositories —
ext-base,ext-admin, and the application skeleton — are being archived under theyii-prefix:webifycms/ext-base→webifycms/yii-ext-basewebifycms/ext-admin→webifycms/yii-ext-adminwebifycms/ext-user→webifycms/yii-ext-userwebifycms/app→webifycms/yii-appwebifycms/theme-green→webifycms/yii-theme-greenThey are not deleted. The work was real, and the thinking behind it informed what comes next. But they represent a previous era of the project, and archiving them honestly reflects that.
The New Architecture
Domain-First Development
The new foundation starts with a pure PHP domain layer —
webifycms/domain. No framework classes. No database abstractions. No HTTP concerns. Just PHP 8.4, strict types, and well-defined business logic.The domain is organised around bounded contexts — the natural boundaries of the CMS problem:
Each bounded context contains Entities, Value Objects, Domain Events, Repository interfaces, and Domain Service interfaces — and nothing else. The implementations of those interfaces reside in the infrastructure layer, completely separate.
The Extension Architecture
Every major feature of WebifyCMS will ship as an independently installable extension — a Composer package that follows the same layered structure:
This means a developer running a simple information site can install only
ext-blogandext-site. A developer building an enterprise application can addext-marketplace,ext-ai-assistant, and custom extensions of their own — all following the same predictable structure. Nothing is mandatory except the shared kernel.Why Extensions Not a Monolith
WordPress's greatest strength was never its code. It was the ecosystem that its plugin architecture enabled. WebifyCMS takes that lesson seriously — but replaces procedural hooks and global filters with a proper domain event system and well-defined interfaces. Extension developers work against documented contracts, not implementation details.
The Infrastructure Decision: Performance Above All
The most consequential technical decision in this pivot is the choice of infrastructure components. And it is driven by a single, non-negotiable constraint:
WebifyCMS must run on shared hosting with limited resources.
A CMS that cannot run on the same infrastructure as WordPress cannot replace WordPress. That constraint ruled out several otherwise attractive options and led to the following stack.
Symfony Components, Not Full Symfony
Rather than adopting the full Symfony framework, WebifyCMS uses Symfony's individual HTTP and DI components assembled deliberately:
symfony/http-kernel— request/response lifecyclesymfony/routing— explicit route definitionssymfony/dependency-injection— compiled containersymfony/console— CLI commandssymfony/event-dispatcher— synchronous event dispatchingThe key word is compiled. Symfony's DI container compiles down to a plain PHP file at cache time — effectively a flat array of factory functions. On a warm request with OPcache active, the container has near-zero overhead. There is no reflection, no auto-discovery, no service scanning. Every binding is explicit.
This is the opposite of full-framework magic. It is the right trade-off for shared hosting.
Eloquent Standalone, Not Full Laravel
For the database layer, WebifyCMS uses
illuminate/database— Laravel's Eloquent ORM extracted as a standalone package. This provides:Memory cost: approximately 1–2MB. Compare that to 10–15MB for a full Laravel bootstrap. On a shared host serving concurrent requests within a 256MB limit, that difference is not academic — it is the difference between the application working and running out of memory.
Target Footprint
WordPress typically costs 8–20MB per request depending on active plugins. WebifyCMS targets less than that before application code runs.
Queue on Shared Hosting
Shared hosting does not support persistent queue workers. WebifyCMS solves this with two implementations of the same
DomainEventBusInterface:SyncEventBus— dispatches domain events immediately within the current requestQueuedEventBus— stores events in a database table, processed by a cron-triggered workerExtension developers declare which events should be async. The domain layer does not know or care which bus is active. Operators choose based on their hosting environment.
Developer Experience as a Design Constraint
Performance was the primary driver of the infrastructure decisions. But developer experience runs a close second — and the two are not in conflict here.
The PHP developer community is, at this point, largely familiar with Eloquent's query builder API and with Symfony's service container concepts. By composing these known tools rather than introducing a bespoke framework, WebifyCMS extension developers can be productive quickly without having to learn an entirely new ecosystem.
The architecture asks something of developers — understanding bounded contexts and the distinction between domain and infrastructure — but it rewards that understanding with a codebase that is genuinely navigable, testable without a running framework, and honest about where business logic lives.
This is the core promise of WebifyCMS to developers: fewer surprises, clearer boundaries, and a platform you can actually reason about.
Current State
As of June 2026:
webifycms/domain— active development, domain layer more than half completewebifycms/yii-ext-base— archivedwebifycms/yii-ext-admin— archivedwebifycms/yii-app— archivedext-base,ext-user,apprepositories — to be createdThe domain layer will be completed first. Infrastructure follows. The sequence is intentional — build the business logic correctly before deciding how to deliver it.
WebifyCMS is open source. The architectural decisions documented here are made in public, with full reasoning, because the developers who build on this platform deserve to understand the foundation they are standing on.
Beta Was this translation helpful? Give feedback.
All reactions