{"id":98055,"date":"2026-10-09T12:38:00","date_gmt":"2026-10-09T16:38:00","guid":{"rendered":"https:\/\/overcentral.com\/en\/?p=98055"},"modified":"2026-09-29T08:04:06","modified_gmt":"2026-09-29T12:04:06","slug":"wordpress-to-emdash-migration-3-days-98055","status":"publish","type":"post","link":"https:\/\/overcentral.com\/en\/wordpress-to-emdash-migration-3-days-98055\/","title":{"rendered":"How a University Department Moved from WordPress to EmDash in 3 Days"},"content":{"rendered":"<p>Most WordPress migrations are defined by what you carry over. This one was defined by what they left behind.<\/p>\n<p>A university communications department had run their site on WordPress for 12 years. They had 4,000+ posts, 200+ pages, and 30+ plugins. The usual story: a contact form plugin, an SEO tool, a caching layer, a page builder, and a dozen single-purpose extensions that had accumulated like barnacles.<\/p>\n<p>They migrated to <a href=\"https:\/\/emdash.com\" target=\"_blank\" rel=\"noopener noreferrer\" data-iacss-external=\"1\">EmDash CMS<\/a> <a href=\"https:\/\/overcentral.com\/en\/ai-personalized-fraud-emails-80983\/\" title=\"Threat Actor Generates 1M Personalized Fraud Emails in 3 Days\" data-iacss-internal=\"1\">in 3 days<\/a>.<\/p>\n<p>Not weeks. Not months. Three days.<\/p>\n<p>Here is what they did that most teams get wrong.<\/p>\n<h2>The Export Trap<\/h2>\n<p>The standard WordPress migration playbook is a WXR export. Download an XML file, import it somewhere else, pray the field mappings line up.<\/p>\n<p>That approach breaks on EmDash.<\/p>\n<p>EmDash stores content as portable text \u2014 structured JSON, not HTML. WordPress stores content as HTML blobs inside <code>wp_posts<\/code>codecodecodecode. A direct 1:1 dump produces a mess. Gutenberg block HTML, shortcodes, and inline styles all get serialized as raw text.<\/p>\n<p>The university team skipped the WXR export entirely.<\/p>\n<p>They used the EmDash WordPress import plugin, but they did not run it blind. First, they mapped every custom field to a content type schema. Then they transformed the data. The import plugin handled the mechanical part. The schema design was the real work.<\/p>\n<h2>Content Types Are the Bottleneck<\/h2>\n<p>WordPress ships with two content types: posts and pages. Everything else requires custom post types, usually managed through a plugin like ACF or JetEngine.<\/p>\n<p>EmDash treats content types as a first-class primitive. You define them in the admin interface or through code. The university team created 7 content types: News Article, Event, Profile, Department Page, Research Output, Publication, and FAQ.<\/p>\n<p>Each type had its own field set. No ACF. No CPT plugin. No meta table joins.<\/p>\n<p>The team&#8217;s lead developer said the schema design took 6 hours. The actual data migration took 4 hours after that. Most teams reverse this ratio \u2014 they spend days trying to fix a bad import instead of hours designing a clean schema.<\/p>\n<h3>Portable Text vs. Gutenberg Blocks<\/h3>\n<p>Gutenberg blocks are HTML with comments. Portable text is structured JSON with block-level metadata.<\/p>\n<p>The university team had 1,200+ posts built with the Classic Editor and another 800 built with Gutenberg. They did not try to preserve the exact block structure. Instead, they extracted the semantic content \u2014 headings, paragraphs, images, embeds \u2014 and mapped them to EmDash&#8217;s block editor.<\/p>\n<p>They lost some layout fidelity. A few multi-column layouts needed manual adjustment. But they gained something more valuable: clean, machine-readable content that an <a href=\"https:\/\/overcentral.com\/en\/meta-muse-ai-agent-80441\/\" title=\"Meta Launches Muse AI Agent, Needs User Trust\" data-iacss-internal=\"1\">AI agent<\/a> or API could consume without parsing HTML.<\/p>\n<h2>Why Plugin Sandboxing Accelerated the Migration<\/h2>\n<p>The university ran 30+ plugins. Most fell into three categories:<\/p>\n<ul>\n<li><strong>Security and performance<\/strong> (Wordfence, W3 Total Cache, Redirection)<\/li>\n<li><strong>Content extensions<\/strong> (ACF, Yoast SEO, Duplicate Post)<\/li>\n<li><strong>Single-purpose tools<\/strong> (a specific events calendar, a specific form builder)<\/li>\n<\/ul>\n<p>EmDash ships with SEO, caching, redirects, and form handling built in. That eliminated 8 plugins immediately.<\/p>\n<p>The remaining plugins needed porting. This is where dynamic workers changed the timeline.<\/p>\n<h3>Dynamic Workers for Plugin Porting<\/h3>\n<p>EmDash runs every plugin in its own V8 isolate. The plugin cannot touch the database, the file system, or any other plugin unless the capability manifest explicitly grants it.<\/p>\n<p>The university team used <a href=\"https:\/\/overcentral.com\/en\/ai-influencer-monetization-96595\/\" title=\"How to Monetize an AI Influencer Without Sponsors\" data-iacss-internal=\"1\">an AI<\/a> coding agent connected to EmDash&#8217;s MCP server to port their custom plugins. The agent read the existing PHP plugin code, generated TypeScript equivalents, and scoped the permissions.<\/p>\n<p>A custom events plugin that required <code>read_content<\/code>codecodecodecode and <code>write_content<\/code>codecodecodecode permissions took 90 minutes to port. The WordPress equivalent had no permission scoping at all \u2014 it accessed <code>wpdb<\/code>codecodecodecode directly.<\/p>\n<p>The sandbox model meant the team could deploy plugins without worrying about side effects. If a ported plugin had a bug, it could not corrupt the database or leak data. The isolate contained the damage.<\/p>\n<h2>The 3-Day Migration Pipeline<\/h2>\n<h3>Day 1: Content Audit and Schema Design<\/h3>\n<p>The team audited every custom post type, taxonomy, and field. They documented which WordPress features had EmDash equivalents and which needed custom development.<\/p>\n<p>They found that 22 of their 30 plugins had functionality already in EmDash core. The remaining 8 were custom or niche tools that required porting.<\/p>\n<h3>Day 2: Data Transformation and Plugin Porting<\/h3>\n<p>The team ran the EmDash import plugin against a staging environment. They used the MCP server to batch-update field mappings. An AI agent ported the 8 remaining plugins, one at a time, with human review of the capability manifests.<\/p>\n<p>The most complex plugin \u2014 a custom event registration system \u2014 required 3 hours of porting and testing. The sandbox caught a data validation bug during testing that would have gone unnoticed in WordPress until the production database had bad records.<\/p>\n<h3>Day 3: Theming, QA, and DNS Cutover<\/h3>\n<p>EmDash themes are built with Astro. The university&#8217;s WordPress theme was a commercial product with heavy PHP dependencies. They could not port it directly.<\/p>\n<p>Instead, they built a new Astro theme from one of EmDash&#8217;s starter templates. The lead developer said the new theme loaded in under 200ms on Cloudflare&#8217;s edge network. The old WordPress theme, with its PHP rendering and multiple plugin hooks, took 2-3 seconds even with caching.<\/p>\n<p>QA caught 12 issues. None were data loss. Most were CSS edge cases from the portable text rendering.<\/p>\n<p>DNS was the only step that took longer than expected. The university&#8217;s IT department required 24 hours notice for DNS changes. The technical migration was complete in 2.5 days. The institutional process added the remaining half day.<\/p>\n<h2>What the Team Left Behind<\/h2>\n<p>The 30 plugins became 0.<\/p>\n<p>The 4,000 posts became portable text.<\/p>\n<p>The $1,200\/month managed WordPress hosting bill became a $5\/month Cloudflare Workers plan plus R2 storage.<\/p>\n<p>The team&#8217;s monthly infrastructure costs dropped by 92%. But that comparison is only valid for content-heavy, transaction-light sites. A university department does not run WooCommerce or a membership system. Their plugin surface was mostly content management, not e-commerce.<\/p>\n<h2>The Edge Case Where This Fails<\/h2>\n<p>EmDash is not a universal WordPress replacement. The team succeeded because their site was content-forward and plugin-light in terms of business logic.<\/p>\n<p>A site running LearnDash, WooCommerce, or a complex LMS plugin will struggle. Those plugins represent years of development and thousands of dollars in licensing. Porting them to EmDash&#8217;s sandbox model requires rebuilding the business logic from scratch. The 3-day migration becomes a 3-month project.<\/p>\n<p>For universities evaluating EmDash, the question is not &#8220;can we migrate?&#8221; It is &#8220;can we survive without our top 3 plugins?&#8221;<\/p>\n<p>The communications department could. Their top plugins were SEO, forms, and caching \u2014 all replaced by EmDash core. That is why 3 days was realistic.<\/p>\n<p>For a department running a custom LMS with student data, 3 days is a fantasy. The architecture is better, but the ecosystem gap is still real.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Most WordPress migrations are defined by what you carry over. This one was defined by what they left behind. A university communications department had run their site on WordPress for 12 years. They had 4,000+ posts, 200+ pages, and 30+ plugins. The usual story: a contact form plugin, an SEO tool, a caching layer, a [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":100097,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/cards.overcentral.com\/cards\/en\/98055.png","fifu_image_alt":"How a University Department Moved from WordPress to EmDash in 3 Days","footnotes":""},"categories":[31],"tags":[],"class_list":["post-98055","post","type-post","status-publish","format-standard","has-post-thumbnail","category-technology"],"fifu_image_url":"https:\/\/cards.overcentral.com\/cards\/en\/98055.png","fifu_image_alt":"How a University Department Moved from WordPress to EmDash in 3 Days","_links":{"self":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts\/98055","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/comments?post=98055"}],"version-history":[{"count":1,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts\/98055\/revisions"}],"predecessor-version":[{"id":100098,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts\/98055\/revisions\/100098"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/media\/100097"}],"wp:attachment":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/media?parent=98055"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/categories?post=98055"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/tags?post=98055"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}