Skip to content
gioser
ES

tawasuyu · Making

Your WordPress, without WordPress: the same site to the pixel, without a single line of PHP

A WordPress site is a program that runs every time someone visits, with its database, its plugins and its admin doors open to the internet. qhatu takes it whole, identical to the pixel, and leaves nothing to execute: the same site, faster, and without a single line of PHP.

8 min readBy Gioser Editorial

Every time someone opens a page of a WordPress site, a program starts on the server: it reads the database, loads the theme, wakes up every plugin, builds the HTML and sends it. The same thing, over and over, for text that changes once a month. And all the while, that program leaves the doors it is administered through open to the whole internet. This article tells how qhatu —tawasuyu's content manager— takes a real WordPress site whole, leaves it identical to the pixel, and strips away everything that could be attacked.

Chart: on the left, WordPress with 9 of 9 programs answering anyone, with the list of their addresses —wp-login.php, wp-admin, xmlrpc.php, wp-json, the user list, author=1, readme.html, install.php, wp-cron.php—; on the right, qhatu and saywa with 0 of 9, 0 different pixels out of 3,278,400, 825 to 135 milliseconds and zero PHP
Measured on October 24, 2026 on a client's real site and its copy.

The site that gets built on every visit

WordPress is the most common way to have a website, and for good reasons: it installs in an afternoon, there is a theme for everything, and a builder like Elementor lets you design without writing code. The price is paid later, in installments. Every plugin is someone else's code running with all of the site's permissions; every postponed update is an open door; and the database, the login and the API keep listening around the clock, even if the site is edited by one person twice a month.

The site everything here was tested on belongs to a real client: a retreat center built with WordPress, the WoodMart theme and Elementor Pro, with 64 pages, a gallery, a blog and two contact forms. An ordinary site, the kind there are millions of. The request was simple: keep it exactly the same, and keep it easy to edit.

One command

What was done by hand on the first day —downloading the rendered site, cleaning what WordPress appends to every file name, re-pointing the forms— is now a verb:

qhatu absorb-wordpress https://the-site.com/ folder

It reads the sitemaps WordPress publishes, downloads every page and everything it needs —stylesheets, scripts, images in all their sizes, fonts, icons—, and points every reference at the local copy. It skips what isn't content: the cart, the admin panel, the feeds, the searches. If an old address redirects to another, it does not duplicate it: it records it as a redirect for the server, so a link someone shared years ago still arrives. On the client's site:

whatmeasured
pages64
resources (stylesheets, scripts, images, fonts)448, 45 MB
time, with a courtesy pause between requests6 minutes
broken references in the copy0

Identical to the pixel, with a control arm

"Exactly the same" can be measured. The same page of the original and of the copy was opened in Chrome at 1366 by 2400 pixels, and the two captures were compared point by point. On the home page and on a blog post: 0 different pixels out of 3,278,400. For that zero to mean something, the test carries a control arm: each capture has 216,987 distinct colors, so these are not two blank pages being compared.

Honesty includes what did not come out as zero. On a third page, 1,785 pixels differed in the menu strip. Before blaming the copy, the original was compared with itself, twice: 1,642 and 0. It is the page itself, which does not paint the same way twice in a row.

Nothing to hack

A WordPress scanner always starts the same way: it asks for the addresses every WordPress has. That same question was put to both sites, in passive mode —read requests to public addresses only, without trying a single password—:

addresswhat it isWordPresscopy
/wp-login.phpthe login dooranswers404
/wp-admin/the admin panelanswers404
/xmlrpc.phpthe classic door for batch brute forceanswers404
/wp-json/the APIanswers404
/wp-json/wp/v2/usersthe list of who can log inanswers, with 3 names404
/?author=1the first author's user nametells itno
/readme.htmlthe exact versionanswers404
/wp-admin/install.phpthe installeranswers404
/wp-cron.phptasks anyone can triggeranswers404

Nine out of nine against zero out of nine. On top of that, the original announced in its own code the exact version of WordPress and of two of its plugins: exactly what an attacker looks for to cross against a list of known flaws. It is not that the copy keeps those doors better shut: it doesn't have them. There is no PHP to run, no database to query, no users to guess.

Measuring this turned up a detail worth telling. The copy still said "WordPress" in an invisible tag in its HTML, inherited from the original: a scanner read it and announced a WordPress that no longer existed. The absorber now removes it.

And the contact forms, which in WordPress are one more plugin? On the copy they are handled by a 205 KB WebAssembly function that runs on the server with declared capabilities: it can store what arrives and read the clock, and nothing else. It cannot read the disk or reach the network; what it didn't ask for doesn't exist for it. The messages are read in the panel, and download as a spreadsheet.

Faster, and measured without cheating

Five pages, five cold loads on each side —a fresh browser per load, no cache—, alternating original and copy so a bad stretch of network doesn't land entirely on one side. The medians:

pagefirst bytelargest paintfull load
home2.5 s → 0.9 s6.1 s → 4.9 s9.9 s → 5.9 s
service page1.9 s → 0.8 s6.5 s → 3.8 s14.9 s → 5.4 s
long page with gallery2.3 s → 0.9 s11.7 s → 6.3 s22.3 s → 7.9 s
blog listing2.4 s → 0.7 s4.5 s → 4.1 s5.1 s → 5.3 s
a blog post2.3 s → 0.8 s5.9 s → 2.5 s7.0 s → 5.2 s

The bytes that travel are practically the same: it is the same page. What changes is the server. And there is a caveat an honest article has to make: the two sites live on different servers, in different places, and the copy was closer to where the measurement was taken. So the network was separated from the software. Opening the connection costs 392 milliseconds to the original and 179 to the copy; that is distance, not code. Subtracting one round trip on each side, what is left is the work of building the page:

WordPress: ~825 ms per page saywa: ~135 ms per page
The server's work, with network distance subtracted. Measured with curl, five requests on each side.

And it is still edited, in place

A static copy you can't touch would be a museum. qhatu's is edited from a panel that lives at its own address —nothing on the public site links to it—, on the page itself, as it looks:

All of that runs on saywa, tawasuyu's web server. On the machine where this site lives, saywa and the project's own forge have already replaced four programs: the web server, the git forge, the proxy and the PHP interpreter. Someone wrote both pieces from scratch, in Rust, with a rule that repeats across the whole project: what wasn't measured isn't claimed.

What it doesn't do yet

How to see it

qhatu lives in the tawasuyu repository —git.tawasuyu.net, on its own server— under 02_ruway/qhatu, and saywa under 03_ukupacha/saywa. The two instruments behind this article, the exposure probe and the speed one, are in scripts/qhatu-careo/: anyone can run them against their own WordPress and its copy, and compare.

Background