Disclosure: I build ShipPress, the Mac app I use for the example near the end. Everything before that section works with any local WordPress setup and any AI coding agent.
Your AI agent built the site on your laptop, and every page looks right at localhost. Then you try to put it online and the reservation form returns a 404, the search box goes nowhere and half the links still point at http://localhost:8080.
I've moved a fair few of these sites now, mostly small business sites built with Claude Code or Codex. The first decision is whether you need WordPress running on the live site at all. Everything else follows from that answer.
Step 1: Find out what you actually built
AI agents tend to add things you didn't ask for. Before you choose how to move the site, open it and list anything that needs PHP after the page has loaded:
- a contact or booking form
- comments
- a shop (WooCommerce)
- member logins
- a search box
A quick way to catch forms is to search the theme and the rendered pages for where they send their data:
grep -rnE "admin-post\.php|admin-ajax\.php|wp-comments-post\.php" wp-content/themes/
Agents love admin-post.php for forms because it's the documented WordPress way to handle a custom POST. That's fine on a live WordPress install. On a static copy the file doesn't exist, so the form posts into nothing.
If your list is empty (or only has search), a static copy will probably do. If it has a shop, logins, comments or forms you want to keep as they are, move the full site.
Option A: A static copy
A static copy is every page saved as plain HTML, plus the CSS, JavaScript and images it uses. You can host it on Netlify, GitHub Pages, Cloudflare Pages or any web server. There's no database to patch, which is a big part of the appeal.
The usual route is a static export plugin (Simply Static is a common choice) or a crawler such as wget --mirror. Whichever you use, check these before you upload:
Permalinks. If the site still uses plain links like /?p=123, a static host sees every page as the same file. Go to Settings › Permalinks, choose Post name and save, then export again. Pages come out as menu/index.html, about/index.html and so on, which every static host understands.
Local addresses. Search the exported folder for localhost and 127.0.0.1. Also search for the escaped form localhost:8080\/, which hides inside inline JSON and block markup:
grep -rlE "localhost|127\.0\.0\.1" ./static-export/
Media. Make sure every size in each image's srcset was saved as well as the original. Open a few pages on a phone-sized window and watch the network tab for 404s. Background images set in CSS are the ones crawlers miss most often.
Forms. Anything posting to admin-post.php, admin-ajax.php or wp-comments-post.php needs a replacement. Your static host may offer form handling, or you can point the form at a form service. Otherwise, swap it for a plain mailto: link or your booking provider's widget.
Search. WordPress search is a query (/?s=udon) that PHP answers. On a static copy you need a client-side index (Pagefind or Lunr) or you remove the search box.
404, robots and sitemap. Check that you have a 404.html and that robots.txt doesn't still say Disallow: / from development.
Option B: Move the full WordPress site
If the site needs PHP, it needs a WordPress host. The move has three parts.
1. Files. You only need wp-content (themes, plugins, uploads). Install a fresh WordPress on the host and let it keep its own wp-config.php with its own database login.
2. Database. Export it and import it on the host:
wp db export site.sql
# on the host, after uploading the file
wp db import site.sql
Watch out if your local setup uses SQLite. Many quick local tools do, and most hosts run MySQL or MariaDB, so you need to convert the database before you import. A plugin-based migration tool can do this for you.
3. Addresses. Replace the local URL everywhere, including serialised data, which a plain find-and-replace in a text editor will corrupt:
wp search-replace 'http://localhost:8080' 'https://example.co.uk' --all-tables --precise
Then check these four things on the live site:
- Permalinks: visit Settings › Permalinks and click Save once so the host writes its rewrite rules. If inner pages 404 while the home page works, this is nearly always the cause.
-
Media: confirm
wp-content/uploadsarrived with the right file permissions and that image URLs usehttps. -
Forms: send a real test. Many hosts block PHP's
mail(), so a form can show "thanks" and quietly send nothing. Set up SMTP if it does. -
Search: search for a word you know is on a page. If results are empty, the import probably missed tables or the table prefix differs from
wp-config.php.
Leave out what only made sense locally: SQLite plugins, local sign-in helpers and any files your AI tool used for its own notes or history.
How I do it with ShipPress
ShipPress is a free Mac app I make that lets your AI coding tool (Claude Code, Codex, Cursor CLI and others, on your own account) build a WordPress site locally. Each site is a normal WordPress folder in your home folder, with the database as a single SQLite file in wp-content/database. You can always take it and leave.
For a static copy, Go live has a link at the bottom of the Free address tab: "Only want the files? Download the static copy". It saves every page, then checks the result before you upload anything. It looks for plain permalinks, leftover local addresses, a shop, links to wp-admin and forms that post to PHP. In the video it caught ?p=123 addresses, and the fix was the Permalinks step above. The output has index.html, one folder per page, a 404 page, robots.txt, a sitemap and a headers file. When a page has a search box, it also adds a small search index that runs in the browser.
For the full site, the WordPress host tab connects to a host once. InstaWP, Hostinger and Pressable connect directly, xCloud and Kinsta take an API key, and Cloudways takes your email and an API key. Any other host with SSH works through Connect with SSH. Go live then exports the database as a MySQL backup, swaps the local address for the live one and packs wp-content. It leaves out the SQLite plugin, the local sign-in helper, ShipPress's editing helpers, its own .aiwp folder and wp-config.php.
Changing hosts later works the same way in reverse: download the site from the old host as a new local site, connect the new host and click Go live.
Here's the whole flow on a restaurant site, Hinoki Udon, from the site folder to the static copy and the WordPress host tab:
The written version, step by step: https://shippress.codotx.com/docs-export-move?ref=devto-en
A short checklist
- List what needs PHP before you choose: forms, comments, shop, logins, search.
- Static copy: Post name permalinks first, then grep for
localhostandadmin-post.php. - Full move:
wp-contentplus the database,wp search-replacewith--precise, then save Permalinks once on the host. - Test a real form submission on the live site.
- Search visibility: in Settings › Reading, untick "Discourage search engines from indexing this site" (or run
wp option update blog_public 1). When ticked, WordPress adds anoindexrobots meta tag to every page and turns offwp-sitemap.xml. Before exporting, grep the export fornoindex. For a full move, check the setting again on the live site after the import, and confirm one page with URL Inspection in Search Console before you submit the sitemap.
Thanks to a reader for pointing out this one.
Which part of the move has caught you out with an AI-built site? For me it was a booking form that worked perfectly on my laptop and posted to admin-post.php on a static host.
- ShipPress (free, Mac): https://shippress.codotx.com/?ref=devto-en
- Issues and feedback: https://github.com/oberonlai/shippress-releases/issues
Oberon Lai
Top comments (2)
Your point about robots.txt still saying Disallow: / from development has a twin worth adding to the checklist. If "Discourage search engines from indexing this site" was ticked under Settings › Reading while the agent was building, WordPress prints a noindex robots meta tag into the head of every page.
On a static copy that tag is baked into every HTML file, so fixing robots.txt alone changes nothing. Run the same grep you use for localhost on the exported folder, searching for noindex instead.
The same setting also turns off the core WordPress sitemap, so the export can ship with no sitemap at all and nothing looks broken.
On a full move the setting lives in the database, so it travels with the import. Untick it on the live site, then run one page through URL Inspection in Search Console to confirm Google sees it as indexable before you submit the sitemap.
Great catch, thank you. You're right that the "Discourage search engines" checkbox is the sneakier of the two: WordPress adds the noindex robots meta tag to every page and also switches off the core wp-sitemap.xml, so a static export can look perfectly fine and still be invisible to Google.
I'll add it to the checklist in the post. Before exporting, untick Settings > Reading (or run
wp option update blog_public 1), then grep the exported folder fornoindexthe same way as for localhost. For a full move, check the setting again on the live site after the import, and confirm one page with URL Inspection in Search Console before submitting the sitemap, exactly as you said.Oberon Lai