TL;DR: Migrating from WordPress requires more than moving data; it requires remodeling unstructured wp_postmeta into strict JSON blocks. We built a dedicated migration controller to handle this, including the complex logic of preserving "dirty" unsaved draft states.
The PostMeta Swamp
Migrating off WordPress isn't a simple data dump. It is a fundamental remodeling of how your application thinks about data. WordPress crams everything that isn't a title or body into wp_postmeta, resulting in a chaotic, unindexed swamp of serialized PHP strings. When we built the migration tooling for StakCMS, we couldn't just import that mess. We had to map it to our strict ContentBlock architecture.
Programmatic Translation
We built BlogMigrationService specifically to handle this translation programmatically. It reads the raw HTML and meta-keys, and forces them into JSON schemas.
But the hardest part wasn't the text; it was the state. In headless systems, you usually have a Draft and a Published state. If a post was published in WP, then edited but not published again, we have to preserve that dirty state without destroying the live snapshot.
// BlogMigrationService.php
if ($entry->last_published_at !== null) {
$this->promotePost($post);
// Mirroring "Modified" status:
// If it was edited after being published, we revert the new post's
// last_published_at so the UI knows it has unsaved drafts.
if ($entry->updated_at->gt($entry->last_published_at->addSeconds(5)))
{ $post->update(['last_published_at' => $entry->last_published_at]);
}
}



