5 minutes reading time (1037 words)

Crossing CMS Borders: Migrating across Worlds with a Common Content Model

Crossing CMS Borders: Migrating across Worlds with a Common Content Model

Love databases? I do too. I’ve always loved working with structured data, and that passion led me to develop a smart, dynamic way to migrate content from WordPress to Joomla. No scripts, fewer hardcoded hacks - a clean model and maintainable design.

When I joined Joomla’s Google Summer of Code 2025, I didn’t just want to write code - I wanted to build something useful, something maintainable, and something that leaves a beautiful impression even after the project ends. I didn’t want it to be just a summer assignment that gets archived; I wanted it to be a tool people use, now and in the future.

That’s why I applied to this project - Migrating CMSs using Common Content Model (CCM) and a model-driven engineering approach (MDE). My Name is Reem Atalah a backend Engineer from Cairo, Egypt.

Participating in Google Summer of Code 2025 with Joomla has sharpened my technical skills, with the most important one being how to collaborate in an enormous codebase and learning exactly where to make my contribution. Joomla showed me the power of open-source and collaboration.  I’ve learned how to test, document, and structure code in a way that allows others to pick it up and extend it easily.

The goal of my project is ambitious: enable smooth, structured migration between CMSs using a CCM. And for model-driven engineering, I am now defining the model in JSON files in a schema directory within the project. Instead of hardcoded logic tied to a specific source or destination, we define JSON-based mappings that describe how content should be translated.

For example, we have two mapping files:

  • wordpress-ccm.json – Describes how data is extracted from WordPress

  • joomla-ccm.json – Describes how that data maps into Joomla’s API

Here’s a snippet from our media mapping:

{
  "type": "media",
  "config": {
    "endpoint": "media/files"
  },
 "properties": {
   "id": "id",
    "title": "title",

    "media_type": "type"
  }
}

The previous JSON structure is the core of how the system works. Each type (like media) defines a specific content entity to migrate. The config section tells the engine where and how to send the data - for example, to Joomla’s media/files endpoint. The properties section maps fields from the CMS (here it’s Joomla) to their equivalent in CCM (CCM is implicitly structured within the JSON of each CMS). So when we define "media_type": "type", we’re telling the system, “take the 'type' from the CCM and push it into Joomla’s 'media_type' field.” By writing or modifying these JSON files - like wordpress-ccm.json - developers can easily support new content types or platforms without touching the core migration logic.

This allows the migration logic to stay generic, reusable, and adaptable. You don’t have to dig through PHP files and hardcoded field mapping. Want to build a migration from Drupal or a headless CMS? Just write a new cms-ccm.json and map it to Joomla’s model or any other CMSs. This opens the door to supporting other CMSs in the future with minimal changes to the core engine.

How Can You Use It?

First, download the component from here, and you can refer to this guidance on how to use it. 

Let’s have an example, head to your Joomla site, in the sidebar choose Components → CMSs →CMS Management, then you can see the CMSs, click on the CMS you would migrate, and add the essential properties so we can call the CMS APIs.

The following screenshot shows the UI for migrating CMSs, where you can access from Components → CMSs → Migration, then choose the source and target CMSs, click on “Apply Migration”, and it shows what items are migrated and what aren’t (if there are)

This is another example of partial failure in one item (tags), which didn’t corrupt the whole migration

Differences Between Joomla and Wordpress

Some items can have the same meaning with different identifiers between the two CMSs. For example, comments are in the core of WordPress, but in Joomla only available via an extension. In WordPress, there is a difference between Posts and Pages, where Pages don't have categories or tags in WordPress's core, while in Joomla, we have Articles only, so both Posts and Pages are mapped to Articles. Also, an article normally only has one category in Joomla; however, in WordPress, it can have several categories. Menu items in Joomla are more varied than WordPress. 

What’s Migrated So Far - and Why It’s Not Always Simple

So far, the migration covers categories, tags, media, articles, menus, and menu items, with users currently in progress. But migrating from WordPress to Joomla isn’t just about matching content types like Post to Articles - it’s about reconciling two different content philosophies. We can’t always have a one-to-one match from WordPress to Joomla. Things like media within text handling, URLs, and inherited fields (e.g. Article has a category, this category needs to be migrated before the article and must use the new migrated category ID) required careful mapping and transformation. These incompatibilities made it clear that a rigid, hardcoded solution would never scale—and that’s exactly why we built a dynamic, model-based system from the outset.

To make sure everything works as expected - now and in the future - I backed the work with solid testing: unit tests for logic and Cypress for full end-to-end coverage.

What Can You Use It For?

Imagine you're building a site for a client who’s using an outdated WordPress blog. With this tool, you can automate the migration to Joomla, saving hours of manual work. Additionally, the use of CCM allows for the same framework to be reused for future migrations between entirely different platforms.

What’s Coming Next?

I’m excited to work on API Discovery: a way to automatically detect and understand the source or destination API structures. This shall make the system even more adaptable. 

I'm also refining user and custom-fields migrations, adding deeper use cases, and expanding the end-to-end testing with Cypress alongside robust unit tests.

Final Thoughts

As I reflect on this journey, I’m proud that what began as a goal - to build something useful and maintainable - has become a living, evolving project. I hope that this tool becomes part of that vision for many developers to come.

Some articles published on the Joomla Community Magazine represent the personal opinion or experience of the Author on the specific topic and might not be aligned to the official position of the Joomla Project

5
The August Issue
Back to the Future: 20 Years of Joomla!
 

Comments

Already Registered? Login Here
No comments made yet. Be the first to submit a comment

By accepting you will be accessing a service provided by a third-party external to https://magazine.joomla.org/