Skip to content
Friday, 5 June 2026 · LondonENع
Rayan Azhari.Sustainability · Energy · Carbon · Built Environment

I Stopped Paying for WordPress Hosting

Managed WordPress hosting is a tax you pay in money, in performance, and in security anxiety. Here is how I kept the WordPress editor I love, ran it locally for free, and served the public site as static HTML on the edge: a zero-dependency Node crawler I have open-sourced.

Rayan AzhariChartered Environmentalist, MISEP · 7 min read

The free, fast, secure publishing pipeline I built instead, and then open-sourced.

If you run a WordPress blog, a portfolio, or a company site, you are probably paying what I have come to think of as the WordPress Tax.

Managed WordPress hosting starts at around $10–$25 a month, which is $150–$300+ a year, and the bill never quite buys peace of mind:

  • Performance bottlenecks. Every page load fires PHP and queries a database, even for content that has not changed in months.
  • Constant security anxiety. Plugin vulnerabilities, active logins, brute-force attempts and SQL-injection risk are the price of admission.
  • Upgrade fatigue. Core, theme and plugin updates that you apply just to keep the lights on.

So why do we stay? Because the usual escape hatch hurts. Static site generators like Gatsby, Hugo and Astro are excellent, but they ask you to write in Markdown inside a code editor. You give up the best editing dashboard on the web, page builders like Elementor and Divi, and the plugin ecosystem you actually rely on.

I wanted both halves of the deal:

  1. Keep the full WordPress editing experience, running locally on my machine, for free.
  2. Serve the public site as flat static HTML on a global edge network, also for free.

So I built WP Local-to-Static: a zero-dependency, open-source template that does exactly that. This essay is me releasing it.

Why the existing "static WordPress" plugins did not cut it

If you have searched for this before, you have met plugins like Simply Static. They work, until you point them at a local WordPress install (Local WP, for instance). Then reality sets in:

  • They run inside your PHP server. On larger sites that means deadlocks, memory pressure and timeout crashes: the export fights the very runtime it depends on.
  • They break responsive images. WordPress generates several sizes of each image and serves them through the srcset attribute. Naive scrapers grab only the src, so when a visitor opens the site on a phone, the browser reaches for a variant that was never downloaded, and shows a broken placeholder.
  • They leak your local domain. Exported HTML quietly keeps references like http://mysite.local/ buried in breadcrumbs, oEmbed JSON, share-button links and sitemaps. In production, Chrome flags these as Private Network Access (PNA) warnings.

I needed something decoupled from the PHP runtime, and smart enough to understand a modern, responsive, multilingual frontend.

Meet WP Local-to-Static

WP Local-to-Static is a self-contained Node.js crawler that runs entirely outside your WordPress server. It talks to your local site the same way a browser would, as an external HTTP client, so it never touches the PHP deadlock problem at all.

It has zero npm dependencies. The whole thing is built on Node's native fetch (v18+), so npm install pulls down nothing and there is no supply-chain surface to worry about.

The workflow is one straight line:

Write in Local WP  ->  npm run publish  ->  Auto commit & push  ->  Live on Vercel
   (your machine)       (Node crawler)        (GitHub repo)          (global edge CDN)

What makes the crawler actually smart

1. It finds every page, not just the ones you remember. The crawler seeds itself from your WordPress sitemaps (post-sitemap.xml, page-sitemap.xml, category-sitemap.xml, and language variants like /ar/), then recursively discovers and queues every internal link it meets. System routes (/wp-admin/, /wp-json/, feeds, author archives, xmlrpc.php) are filtered out automatically.

2. Deep responsive-image scraping (srcset). It does not just read src. It parses srcset and data-srcset on every <img> and <source>, extracts every mobile, tablet and high-resolution variant, and downloads them all. It even un-lazyloads images, promoting data-src, data-srcset and data-sizes into real attributes, so pictures render instantly in the static export without waiting on JavaScript.

3. It chases assets inside your CSS, too. The crawler parses url(...) references in your stylesheets and pulls down the fonts and background images hiding in there, the assets most scrapers silently drop.

4. Zero local-domain leakage (PNA-safe). This is the part I am proudest of. The crawler rewrites your local domain to your production domain in three different encodings: plain URLs, escaped slashes inside JSON (https:\/\/...), and URL-encoded share links (https%3A%2F%2F...), across your HTML, CSS, JS, JSON and XML sitemaps. No leaked localhost, no PNA warnings, no surprises in DevTools.

5. Production-ready details, handled for you. Query-string pagination (?query-3-page=2) is rewritten to clean static paths (/page/2/). Unicode and Arabic URLs are decoded correctly so files land on disk with proper names. Sitemaps are rewritten to your live domain so SEO keeps working. And the shipped vercel.json adds sensible security headers out of the box: X-Frame-Options, X-Content-Type-Options: nosniff, a strict Referrer-Policy and a locked-down Permissions-Policy, plus clean URLs and trailing slashes.

6. One command to publish. You never touch Git directly. When a post or a theme change is ready:

npm run publish

That crawls the site, scrubs every local reference, stages the output, creates a timestamped commit and pushes to GitHub. GitHub triggers Vercel, and the update is live in well under a minute.

Getting started in three steps

The kit runs on Windows, macOS or Linux, and the only prerequisites are Node 18+, Git and Local WP.

1. Clone the template

Click "Use this template" on the WP Local-to-Static repo, or clone it directly:

git clone https://github.com/rayan-azhari/WP-Local-to-Static.git
cd WP-Local-to-Static
npm install   # zero dependencies, this just initialises the project

2. Run the setup wizard

npm run setup

The interactive CLI asks four quick questions (your local WordPress URL, your production domain, the output folder, which defaults to public, and whether to inject lightweight Vercel Web Analytics) then writes a wp-static-config.json for you.

3. Import to Vercel

Create a free Vercel project, import your GitHub repo, set the Framework Preset to Other, leave the Build Command empty, and set the Output Directory to public. Click Deploy.

That is it. You are now hosted on one of the fastest global CDNs in the world for $0 a year, and you can attach a custom domain for free in the project settings.

Why you should switch

If your site is mostly informational, a blog, a portfolio, a landing page, then running a live database in production is overhead you do not need. Decoupling the WordPress backend makes your site:

  • Effortlessly scalable. Flat files on a CDN absorb traffic spikes without breaking a sweat or running up a bill.
  • Secure by construction. No database, no PHP, no logins in production: there is simply nothing there to hack.
  • Free. The Vercel Hobby tier covers it, saving you $150–$300+ a year.

You keep the editor you love. You drop the bill and the attack surface. That is the trade I wanted, and now it is a git clone away.

If you try it, I would genuinely like to hear how it goes, including where it breaks.

GitHub: github.com/rayan-azhari/WP-Local-to-Static

Related posts

The Knowledge Escalator

How an ordinary teenager came to out-know Ptolemy, and why the same structural progress makes every one of us more ignorant than anyone who has ever lived. Hand a modern fifteen-year-old a blank sheet of paper and ask them to map the architecture of the cosmos, and they will sketch, without a moment’s hesitation, a

· 14 min

Inheriting Zeus: From the Pantheon to the Possibility Space

Inheriting Zeus: From the Pantheon to the Possibility Space If oxen and horses had hands, and could draw with their hands, they would draw the gods to look like oxen and horses. Xenophanes of Colophon, c. 570 BCE Two and a half thousand years before the science of psychology described projection, Xenophanes had already noticed

· 22 min

Newsletter

Subscribe for new essays.

Unsubscribe anytime. Read by 4,200+ professionals.