๐ What is Mishka CMS Migration?
mishka_cms_migration is the migration extension of Mishka CMS. It moves a site from another CMS into a Mishka CMS site: blog posts, categories, tags and authors, pages, media, redirects, site settings, and the global colours and fonts of a site built with Elementor (as theme tokens in a stylesheet of its own, with a dark-theme twin of each colour). Every record is written by the CMS's own actions as the admin who pressed Import, so the CMS's policies and validations decide, and plugins that react to a change (sitemap, share cards, stylesheet) react as usual.
- [x] WordPress, over its REST API or from the file its Tools โธ Export makes, with Polylang and WPML translations and Elementor layouts
- [ ] Joomla
- [ ] Drupal
- [ ] Ghost
๐ In a host
- Add
MishkaCmsMigrationto the host'sash_domainsand runmix ash.codegenfor the runs and items tables. - Give Oban a
migrationqueue (queues: [migration: 1]). - Install the extension on a site from the CMS's installer, then grant the
admin:dashboard:migrationandadmin:api:migrationpermissions to the site's admin.
Posts, authors, categories and tags are written into Mishka Blog when it runs beside the extension, and skipped when it does not.
๐ How a migration runs
- An admin creates a run: the source, the host it reads from, how to connect, and their choices.
- A dry run reports what an import would create, update and skip. It writes nothing.
- The admin decides on the Items page: leave items out, map a category or tag to one the site has, or settle each conflict marked "Needs your decision".
- The import writes each item through the CMS's own actions as that admin, and saves the report.
Both steps are AshOban jobs on the migration queue. Running again is a new run: it updates what the source changed and keeps what an admin changed in the CMS.
๐ Several sources into one site
- ๐ One site can take content from many sources, such as two WordPress blogs.
- ๐งพ Each item is remembered per site, host, kind and source id, so the same id on two hosts is two items.
- ๐ก๏ธ A clash in the CMS, such as the same address, fails that item with the CMS's reason. Nothing is overwritten.
flowchart LR
A[WordPress blog A] --> M[Mishka CMS site]
B[WordPress blog B] --> M๐๏ธ Layout
The extension is an Ash domain with three resources: a run, its items and its log. Sources and targets are Mishka Installer plugins, and the admin screens are mishka_gervaz. The tests replay responses recorded from a real WordPress.
Folders and files that matter
``` lib/ โโโ mishka_cms_migration.ex the Ash domain and its code interfaces โโโ mishka_cms_migration/ โ โโโ resources/ MigrationRun, MigrationItem and MigrationLog โ โโโ sources/ the WordPress source (REST and export file) and how its content becomes HTML โ โโโ targets/ one module per kind written: pages, media, redirects, settings, โ โ stylesheet, layout, and the Blog's bloggers, collections, tags, posts, comments โ โโโ workers/ what a job does: the walk, the decision, the write, who it runs as โ โโโ source.ex, target.ex the behaviours a source and a target follow โ โโโ events.ex migration:content:convert, migration:item:before_import, migration:import:finished โ โโโ provision.ex installing on a site: its permissions โ โโโ report.ex what a dry run or an import did with each item โโโ mishka_cms_migration_web/ the admin: runs page, items page, routes and sidebar entry test/ behaviour tests, support plugins and the recorded WordPress fixtures dev/ โโโ playground.exs `mix playground`: a run walked through by hand โโโ wordpress/ a real WordPress in Docker, and the scripts that seed and record it ```๐งฉ Part of Mishka CMS
Mishka CMS Migration is an extension of Mishka CMS: Open-Source Multi-Site CMS, built like Mishka Blog: Open-Source Blog Engine and Mishka Document: Versioned Docs Engine: Ash resources, Mishka Installer plugins, mishka_gervaz admin screens and Oban jobs.
๐ Getting started
Add it from Hex, then follow In a host:
{:mishka_cms_migration, "~> 0.0.1"}Open the Migration entry in the admin sidebar, press New import, and start with a dry run.
๐ค Contributing
Clone the repo next to mishka_cms_core, mishka_gervaz, mishka_installer and guarded_struct; mix.exs takes a sibling checkout over Hex when there is one. Then run the checks:
mix deps.get
mix ci
To work against a real WordPress, start the one in dev/wordpress with Docker and seed it as that README says.
๐ฌ Community and support
- Join the Mishka Discord to ask questions, share what you moved and meet the team.
- Report a bug or ask a question in GitHub issues.
- Read about new releases on the Mishka blog.
- For a custom migration or priority support, hire the Mishka team.
๐ Support the project
Mishka CMS and its extensions are free and open source. You can support their development through GitHub Sponsors or Buy Me a Coffee.
๐ License
Apache License 2.0. See LICENSE.