Appearance
Moving a WordPress site to Laravel without moving the content
Ask a Laravel developer how long it takes to rebuild a WordPress site in Laravel and the estimate is usually about the code: the templates, the forms, the admin. Then the project starts, and most of the time goes somewhere else: the data.
Where WordPress migrations really go
A WordPress site that has been running for a few years keeps more in its database than its posts:
- Addresses. The permalink structure, category and tag bases, the static front page, pages nested under pages, attachment pages. Every one of them is a URL that search engines and other sites link to.
- Meta.
wp_postmetaholds a featured image here, an ACF repeater there, SEO titles, a page template, a sort order, and a few keys from a plugin that was removed in 2017. - Options. Settings of WordPress and every plugin, much of it as PHP
serialize()output, sometimes nested three levels deep. - Users. Accounts with WordPress's password hashes and roles. Rebuilding means either a password reset for everyone or reimplementing the hashing.
- Plugin tables. WooCommerce orders, Rank Math redirects, form submissions, social logins. Each in a format only its plugin documents.
A rewrite has to export all of that, design new tables for it, write an importer, test the importer on the real database, freeze the content for the final run, and add redirects for every URL that came out different. It is the part that is hard to estimate, and the part most likely to lose something on the way.
Same database, new application
kitloom removes that step. It is a Laravel CMS whose storage is the WordPress database: Eloquent models over wp_posts, wp_terms, wp_options, wp_users and the plugins' tables, reading every format WordPress and those plugins wrote, including serialized arrays.
Moving a site is pointing a kitloom application at that database:
ini
DB_CONNECTION=mysql
DB_DATABASE=wordpress
DB_PREFIX=wp_ # $table_prefix from wp-config.phpand running php artisan migrate, which adds kitloom's own tables (sessions, queue, roles, the modules') beside WordPress's and leaves WordPress's tables and rows as they were. The site then has:
- the same posts, pages, media, menus, widgets and comments;
- the same URLs, because kitloom handles a request the way WordPress does: the permalink settings, rewrite rules, the main query, the canonical redirect and the template hierarchy;
- the same users, signing in with their WordPress passwords (both the old phpass hashes and WordPress 6.8's bcrypt);
- the same plugin data, read by modules in the plugins' own formats: custom fields, forms, the shop, SEO, redirects. More on that in a separate post.
What you write from then on is Laravel. The public API speaks Laravel names ($post->title, Settings::get(), Menus::get('main')), writes go through writers that fill slugs and dates and check permissions, and every module is a Composer package with service providers, contracts, events and tests.
What is still work
Pointing at the database moves the data, not the look or the custom code:
- The theme. A WordPress theme is PHP for WordPress and does not run. Start from a bundled theme, generate one with every template of the hierarchy, or turn an HTML template into one. Or go headless: every page also answers as JSON.
- Your own code. What
functions.phpor a site plugin did (a post type, a shortcode, an email) becomes a module.php artisan kitloom:make-modulewrites one, with both admins and tests, that passes every check as generated. - Plugins without a module. Their data stays in the database, their shortcodes show as text. The comparison script below finds every page where that happens.
- Files.
wp-content/uploads/is copied to the media disk; old links to/wp-content/uploads/…get a 301 to the new address.
That is real work, but it is work you can estimate, and none of it puts content at risk.
Doing it without risk
Because nothing is converted, the move can be rehearsed for as long as you like. kitloom can even draw the site from the live database with a MySQL user that may only SELECT, so WordPress goes on as it is while you look at the same posts through kitloom. A script then compares the two sites address by address: status codes, redirects, titles, canonical tags, content, lists on archives, leftover shortcodes. How that works step by step is in the next post and in the full guide, Migrate from WordPress.
When everything you care about matches, the switch itself is short: freeze content, take the final copy, php artisan migrate --force, sync uploads, point the domain.
After the move: an agent on the site
Once the site runs on kitloom, it can be run from a chat. kitloom ships an MCP server, so Claude, Cursor or your own agent connects to the site and works with every module: it fixes the 404s the switch left behind, writes the missing meta descriptions, answers form messages, reads the day's orders. It acts as the user whose key it holds, through the same code as the admin. Locked settings stay with people, nothing is deleted for good, and every change is in the activity log. See Run your site from Claude or Cursor.
Try it
Open a sandbox with demo content in one click, Filament or Nova, or go straight to your own site with Migrate from WordPress. What kitloom reads from WordPress and its plugins, and what it does not, is on WordPress Compatibility.