{"slug": "the-ghost-of-php-and-haunted-wordpress-sites", "title": "The Ghost of PHP and Haunted WordPress Sites", "summary": "A developer at Hackers Hostel built WP2Astro, an open-source WordPress plugin that converts legacy WordPress sites into static Astro projects, using Google's open-weight Gemma 4 model to rebuild layouts and strip dead page-builder shortcodes. In a test run on a 2009-era blog, the tool converted 20 entries with 6 media files and preserved 27 old URLs as redirects, producing a layout that was valid on the first attempt in 10 seconds and a full conversion in about 30 seconds, with an Astro build of 33 pages in 0.7 seconds at a cost of a fraction of a cent. The plugin, released under GPL-2.0-or-later, can also run without AI to produce a working static site.", "body_md": "*This is a submission for the [Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine](https://dev.to/challenges/hacktoberfest-week4-2026-10-26)*\n\nNothing 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).\n\nEven 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.\n\nSome 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.\n\nBut the content? The stories, the photographs, the memories? Those deserve to live.\n\n**Thus comes WP2Astro to the rescue.**\n\nPowered by Google's open-weight **Gemma 4**, WP2Astro takes these haunted WordPress sites and gives them a second life as modern, static [Astro](https://astro.build) websites.\n\nNo more PHP runtime. No more abandoned plugins. No more worrying about whether the next update will finally kill the site.\n\nThe ghosts of WordPress's past can finally rest, while everything worth remembering lives on.\n\nIronically, WP2Astro is a WordPress plugin! You install it on the old site, click **Convert**, and here is what happens:\n\n`?p=123`, `?s=search` and `/feed/` all find their way to the right page.\nThe 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.\n\nMeet 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\"*.\n\n**Before. WordPress, 2009:**\n\n**After. Astro, layout rebuilt by Gemma 4:**\n\nSame header photo. Same menu. Same typography.\n\nThe 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.\n\nNow the haunted post. On WordPress, the dead page builder bleeds right through:\n\nAfter Gemma's exorcism:\n\n`[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.\n\n**Numbers from the real run** (Gemma 4 26B A4B through OpenRouter, on my laptop):\n\n| Entries converted | 20 (with 6 media files, and 27 old URLs kept as redirects) | \n| Layout | valid on the first attempt, in 10 s | \n| Whole conversion | about 30 s | \n| Astro build | 33 pages in 0.7 s, 20 indexed for search | \n| AI cost | a fraction of a cent | \n\n**Try it yourself.** Download `wp2astro.zip` from the [latest release](https://github.com/HackersHostel/WP2Astro/releases/latest), 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:\n\n```\nwp wp2astro convert --no-github --zip=./my-site.zip\n```\n\n**Turn a WordPress site into a fast Astro site — same URLs, same look — push it to GitHub, and keep it in sync.**\n\nWP2Astro is a WordPress plugin by [Hackers Hostel](https://hackershostel.com). It converts the site it runs on into an\n[Astro](https://astro.build) project, pushes it to a GitHub repository and keeps that repository up to date as you\npublish. You keep writing in WordPress; your visitors get a static site. Free and open source (GPL-2.0-or-later).\n\n`?page_id=7`\nGPL-2.0-or-later. PHP 8.0+, WordPress 6.5+, and no Composer dependencies.\n\n**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.\n\n**Old URLs are sacred.** The redirect map is the part most migrations skip and later regret. [How to Migrate Off WordPress Without Losing SEO](https://dev.to/techpotions/how-to-migrate-off-wordpress-without-losing-seo-ep8) 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`.\n\n**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.\n\n**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:\n\n`site.json`. It must render the stylesheets and the menu from data, contain a `<slot />`, and carry no PHP, no scripts and no `className=`.`<title>` or `<meta>` tags it writes are stripped, and a generated `<SeoHead />` component takes their place.\n**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.\n\n**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.\n\n**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.\n\n**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.\n\n**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.\n\nThe 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\"?\n\nThat is exactly the problem WP2Astro exists to solve. Twice over.\n\n**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.\n\n**The model is open.** Gemma 4 is an open-weight model. The brain doing the conversion is not rented from a single company.\n\n`wpta_provider`) points it at your own vLLM or Ollama server, so your content never leaves your machines.\n**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.\n\nA 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.\n\nI 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.\n\nDía de los Muertos is about keeping the departed in the room with you. Their photos, their favorite food, their stories.\n\nThe 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.\n\nWP2Astro 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.\n\nThe converted site can live anywhere static: run `npm run build` and publish `dist/`, or run `npm start` on a Node host such as [FlyWP](https://flywp.com) on a DigitalOcean droplet, which also serves the WordPress redirects as real 301s.", "url": "https://wpnews.pro/news/the-ghost-of-php-and-haunted-wordpress-sites", "canonical_source": "https://dev.to/mahmudurrahmanlabib/the-ghost-of-php-and-haunted-wordpress-sites-3b62", "published_at": "2026-10-31 07:45:07+00:00", "updated_at": "2026-10-31 07:49:15.381100+00:00", "lang": "en", "topics": ["ai-tools", "generative-ai", "large-language-models", "developer-tools"], "entities": ["WP2Astro", "Hackers Hostel", "Google", "Gemma 4", "Astro", "WordPress", "OpenRouter", "GitHub"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/the-ghost-of-php-and-haunted-wordpress-sites", "markdown": "https://wpnews.pro/news/the-ghost-of-php-and-haunted-wordpress-sites.md", "text": "https://wpnews.pro/news/the-ghost-of-php-and-haunted-wordpress-sites.txt", "jsonld": "https://wpnews.pro/news/the-ghost-of-php-and-haunted-wordpress-sites.jsonld"}}