WP2Astro 將舊 WordPress 網站轉換為 Astro 靜態網站
The Ghost of PHP and Haunted WordPress Sites
作者 Mahmudur Rahman Labib 開發開源 WordPress 外掛 WP2Astro,將舊 WordPress 網站轉換為 Astro 靜態網站,同時保留內容、外觀與網址。
This is a submission for the Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine
What I Built
Nothing has died more times on the internet than PHP. At this point, PHP has practically become a ghost. Declared dead countless times, yet somehow still haunting the majority of the web with vulnerabilities like PHP2Shell (CVE-2026-109618 and CVE-2026-109619).
Even though PHP powers much of the internet, developers are increasingly moving away from old, haunted WordPress sites. Websites abandoned years ago are still wandering around the internet, running outdated PHP versions, broken plugins, forgotten themes, and shortcodes from page builders that died a decade ago.
Some of these sites haven't seen a developer since 2009. Their owners have disappeared, their plugins have stopped working, and their servers are one PHP update away from sending them to the grave.
But the content? The stories, the photographs, the memories? Those deserve to live.
Thus comes WP2Astro to the rescue.
Powered by Google's open-weight Gemma 4, WP2Astro takes these haunted WordPress sites and gives them a second life as modern, static Astro websites.
No more PHP runtime. No more abandoned plugins. No more worrying about whether the next update will finally kill the site.
The ghosts of WordPress's past can finally rest, while everything worth remembering lives on.
Ironically, WP2Astro is a WordPress plugin! You install it on the old site, click Convert, and here is what happens:
-
Every URL survives. Posts, pages, categories, tags and custom post types keep their exact permalinks. A link shared on a forum in 2009 still lands. Changed slugs,
?p=123,?s=searchand/feed/all find their way to the right page. - The look survives. The theme's CSS, images and fonts come along, and Gemma 4 reads the rendered homepage and rebuilds the header, menu and footer as an Astro layout.
- The ghosts get exorcised. Shortcodes from dead plugins are rewritten into clean Markdown by Gemma, and every change is listed for review.
- It moves into GitHub, and stays in sync. One click creates the repo. Later syncs push only what changed, and the files you edit in the repo are never overwritten.
- SEO comes along for the ride. Titles and descriptions from Yoast, Rank Math or All in One SEO, canonical and Open Graph tags, an RSS feed, a sitemap, robots.txt and static search with Pagefind.
The old site is not destroyed. It is remembered. Same words, same look, same addresses, in a form that no longer needs a PHP server to stay alive.
Demo
Meet the Ghost Town Gazette, a haunted local news blog from 2009 to 2013, still dressed in the Twenty Ten theme. Fifteen posts, three pages, two custom "project" entries, Yoast SEO titles, a post that changed its name, and one cursed entry called "Visual Composer Was Here".
Before. WordPress, 2009:
After. Astro, layout rebuilt by Gemma 4:
Same header photo. Same menu. Same typography.
The sidebar is gone on purpose. Its widgets (search, recent posts, recent comments) were live WordPress features, and the static site gets its own Pagefind search instead.
Now the haunted post. On WordPress, the dead page builder bleeds right through:
After Gemma's exorcism:
[vc_row][vc_column width="1/2"] is gone. The [button] became a normal link. The dead [contact-form-7] was laid to rest. The words around them were not touched.
Numbers from the real run (Gemma 4 26B A4B through OpenRouter, on my laptop):
| Entries converted | 20 (with 6 media files, and 27 old URLs kept as redirects) |
| Layout | valid on the first attempt, in 10 s |
| Whole conversion | about 30 s |
| Astro build | 33 pages in 0.7 s, 20 indexed for search |
| AI cost | a fraction of a cent |
Try it yourself. Download wp2astro.zip from the latest release, upload it under Plugins → Add New, and open WP2Astro in the admin menu. You don't need any account to test it. Pick No AI and you still get a working site, or run it from the command line:
wp wp2astro convert --no-github --zip=./my-site.zip
Code
HackersHostel
/
WP2Astro
Turn a WordPress site into a fast Astro site — same URLs, same look — push it to GitHub and keep it in sync. A WordPress plugin.
WP2Astro
Turn a WordPress site into a fast Astro site — same URLs, same look — push it to GitHub, and keep it in sync.
WP2Astro is a WordPress plugin by Hackers Hostel. It converts the site it runs on into an Astro project, pushes it to a GitHub repository and keeps that repository up to date as you publish. You keep writing in WordPress; your visitors get a static site. Free and open source (GPL-2.0-or-later).
Highlights
- Installs like any plugin. No Node.js, terminal or application passwords on your side: upload the zip, open WP2Astro, click Convert to Astro.
-
Same URLs. Every post, page, custom post type entry, category and tag keeps its permalink, and so do paginated
archives and year, month and author archives. Old links still work: changed slugs,
?p=123,?page_id=7?s=searchand/feed/redirect to the right place. - Same look. The theme's…
GPL-2.0-or-later. PHP 8.0+, WordPress 6.5+, and no Composer dependencies.
How I Built It
Everything happens inside WordPress. Each post is rendered through the_content, so shortcodes and blocks from plugins that are still alive come out as real HTML. Only the dead ones survive as plain text, and those are exactly the ones that get flagged. The HTML is then turned into Markdown. Tables, iframes and other awkward elements stay as raw HTML, so nothing gets lost along the way.
Old URLs are sacred. The redirect map is the part most migrations skip and later regret. How to Migrate Off WordPress Without Losing SEO by techpotions makes that case well. So WP2Astro builds the map automatically from WordPress's own records: old slugs, ?p= and ?page_id= links, ?s= searches and feed URLs. npm start answers them with real 301s, and Netlify or Cloudflare Pages read the same rules from public/_redirects.
Long work, short steps. A conversion is a job split into phases: content, media, AI layout, cleanup, packaging and GitHub. Each step stays under PHP's time limit. The same runner is driven by the admin button, by WP-Cron for auto-sync after you publish, and by WP-CLI.
Gemma is the medium, not the oracle. There is no agent loop. Every AI job is a single prompt with strict rules and a validator watching over it:
- The layout may only import
site.json. It must render the stylesheets and the menu from data, contain a<slot />, and carry no PHP, no scripts and noclassName=. - If the answer breaks a rule, Gemma is told exactly why and gets one more try. If that fails too, a clean default layout takes its place and the report says why. A bad answer never breaks the site.
- The model is never trusted with SEO. Any
<title>or<meta>tags it writes are stripped, and a generated<SeoHead />component takes their place. - A cleanup is rejected if the text length changes by more than 30%, so the model can't quietly "improve" your writing.
My favorite bug was a real ghost in the machine. During testing, one model summoned the dead sidebar. It copied the old "Archives" and "Categories" widgets into the layout, complete with hard-coded links to /2026/10/, monthly archive pages that no longer exist. Ghost links. The fix was two lines of prompt ("leave out widgets and credits") and one line of validation that rejects hard-coded date, category and tag links. Gemma 4 got it right on the first attempt.
Nothing is paid for twice. The layout is reused as long as the theme and menu stay the same, and a cleaned post is reused as long as the post stays the same. Syncing again costs nothing.
Git, without git. Most hosts don't have a git binary, so WP2Astro talks straight to GitHub's Git Data API. It hashes every file the way git does (sha1("blob <len>\0" + content)), compares them with what is already on GitHub, uploads only the new ones, and makes a single commit. A small planner decides what to push, what to delete, and what to leave alone because someone edited it in the repo. That is what makes it safe to let Claude Code, or a human, polish the site and keep syncing.
Your AI, your choice. OpenRouter connects in one click and shows your credit balance right in the dashboard, with a Buy credits button next to it. Already paying for ChatGPT? Sign in with ChatGPT uses your plan instead. And every generated repo ships an AGENTS.md, a CLAUDE.md and Claude Code skills, so a coding agent can finish whatever the conversion couldn't.
Tested against the real world. A mock model server and a mock GitHub API let the whole pipeline run offline, backed by unit tests for the sync planner and the validators. Then I ran it for real, against OpenRouter, a ChatGPT plan and GitHub. The real world found three bugs the mocks never could: OpenRouter quietly dropping part of the callback URL, a stale variable claiming "plan usage not allowed" right after a successful sign-in, and the ghost sidebar above.
Why Does Open Innovation Matter?
The challenge asked a question that hit close to home: does open source make sure what you build "isn't locked inside a service that might disappear someday"?
That is exactly the problem WP2Astro exists to solve. Twice over.
The output is open. A WordPress site dies when its PHP version dies, when its host dies, or when its last maintained plugin dies. What WP2Astro leaves behind is plain Markdown, plain Astro and your theme's own CSS, in a Git repo that belongs to you. Any static host can keep it alive for years, with nothing to patch.
The model is open. Gemma 4 is an open-weight model. The brain doing the conversion is not rented from a single company.
- Today, it runs through OpenRouter for a fraction of a cent per site. No GPU, nothing to install.
- Tomorrow, you can run the same weights yourself. WP2Astro speaks the OpenAI-compatible API, and one filter (
wpta_provider) points it at your own vLLM or Ollama server, so your content never leaves your machines. - If a hosted model changes or disappears, the validators and the fallback make sure the conversion still works.
The harness is open. The plugin is GPL, just like WordPress itself. The prompts, the validators and the sync logic are all there to read, and anyone can tune them for their own theme instead of filing a feature request with a SaaS.
A closed, hosted "migration service" would have been easier to demo. It would also be one more thing that can vanish and take your old site down with it. The very thing this project exists to prevent.
My Agent Session
I built WP2Astro with Claude Code as my pair. It wrote most of the PHP, the mock servers and the tests, while I made the calls: the scope, which AI providers to support, what gets kept on every sync. The real-world tests (connecting OpenRouter, signing in with ChatGPT, the GitHub device flow) we ran together, with me approving every sign-in. This post was drafted with AI assistance and edited by me.
The Spirit of It
Día de los Muertos is about keeping the departed in the room with you. Their photos, their favorite food, their stories.
The early web has a lot of departed in it. Personal blogs. Club pages. Small-town news sites. All kept alive by a server nobody remembers paying for. When that server goes, the stories go with it, and every link that ever pointed at them turns into a 404.
WP2Astro is my ofrenda for those sites. It keeps the words, the photo in the header, and the part I care about most: every address the internet already knows. So the old links still find their way home.
Prize Categories
- Overall
- Best Use of Gemma. Gemma 4 (26B A4B, open-weight) rebuilds the theme layout and exorcises dead shortcodes in the demo, with strict validation, a deterministic fallback and caching around it.
The converted site can live anywhere static: run npm run build and publish dist/, or run npm start on a Node host such as FlyWP on a DigitalOcean droplet, which also serves the WordPress redirects as real 301s.
來源:DEV Community · dev.to




