Saltar al contenido
gioser
EN

tawasuyu · Hacer

Tu WordPress, sin WordPress: el mismo sitio al píxel, con su tienda, sin una sola línea de PHP

Un sitio hecho con WordPress es un programa que corre cada vez que alguien lo visita, con su base de datos, sus plugins y sus puertas de administración abiertas a internet. qhatu se lo lleva entero, igual al píxel —y con su tienda, si la tiene—, y lo deja sin nada que ejecutar: el mismo sitio, más rápido, y sin una sola línea de PHP.

12 min de lecturaPor Redacción Gioser

Cada vez que alguien abre una página de un sitio WordPress, en el servidor arranca un programa: lee la base de datos, carga el tema, despierta cada plugin, arma el HTML y lo manda. Lo mismo, una y otra vez, para un texto que cambia una vez por mes. Y mientras tanto, ese programa deja abiertas a todo internet las puertas por donde se administra. Este artículo cuenta cómo qhatu —el gestor de contenidos de tawasuyu— se lleva un sitio WordPress real entero, lo deja igual al píxel, se trae también su tienda de WooCommerce, y le quita todo lo que se podía atacar.

Gráfico: a la izquierda, WordPress con 9 de 9 programas que contestan a cualquiera, con la lista de sus direcciones —wp-login.php, wp-admin, xmlrpc.php, wp-json, el listado de usuarios, author=1, readme.html, install.php, wp-cron.php—; a la derecha, qhatu y saywa con 0 de 9, 0 píxeles distintos de 3.278.400, 825 a 135 milisegundos y cero PHP
Medido el 24 de octubre de 2026 sobre el sitio real de un cliente y su copia.

El sitio que se arma en cada visita

WordPress es la forma más común de tener un sitio, y hay buenas razones: se instala en una tarde, hay un tema para todo, y un constructor como Elementor deja diseñar sin escribir código. El precio se paga después, y en cuotas. Cada plugin es código ajeno que corre con todos los permisos del sitio; cada actualización que se posterga es una puerta; y la base de datos, el login y la API quedan escuchando las veinticuatro horas, aunque el sitio lo edite una persona dos veces por mes.

El sitio con el que se probó todo esto es el de un cliente real: un centro de retiros hecho con WordPress, el tema WoodMart y Elementor Pro, con 64 páginas, una galería, un blog y dos formularios de contacto. Un sitio común, del tipo que hay a millones. El pedido fue simple: que quede igualito, y que se pueda seguir editando fácil.

Un comando

Lo que el primer día se hizo a mano —bajar el sitio renderizado, limpiar lo que WordPress agrega a cada nombre de archivo, reapuntar los formularios— hoy es un verbo:

qhatu absorb https://el-sitio.com/ carpeta

Lee los mapas del sitio que publica WordPress, baja cada página y todo lo que necesita —hojas de estilo, scripts, imágenes en todos sus tamaños, fuentes, íconos—, y deja cada referencia apuntando a la copia local. No baja lo que no es contenido: el carrito, el panel de administración, los feeds, las búsquedas. Si una parte del sitio la arma JavaScript recién en el navegador, con --render cada página pasa antes por un Chrome sin pantalla y se guarda ya armada. Sobre el sitio del cliente:

quémedido
páginas64
recursos (hojas, scripts, imágenes, fuentes)448, 45 MB
tiempo, con una pausa de cortesía entre pedido y pedido6 minutos
referencias rotas en la copia0

Y no hace falta que sea WordPress: el mismo verbo se llevó un Joomla, una demo de Squarespace que arma todo con JavaScript y el primer sitio web de la historia, el de CERN, con cero referencias rotas en los tres.

Igual al píxel, y con brazo de control

«Igualito» se puede medir. Se abrió la misma página del original y de la copia en Chrome, a 1366 por 2400 píxeles, y se compararon las dos capturas punto por punto. En la portada y en una entrada del blog, 0 píxeles distintos de 3.278.400. Para que ese cero signifique algo, la prueba lleva brazo de control: cada captura tiene 216.987 colores distintos, así que no se están comparando dos páginas en blanco.

Y la honestidad incluye lo que no dio cero. En una tercera página aparecieron 1.785 píxeles distintos en la franja del menú. Antes de culpar a la copia se comparó el original consigo mismo, dos veces: dio 1.642 y 0. Es la propia página, que no se pinta igual dos veces seguidas.

Ningún enlace viejo se rompe

Un sitio con años tiene enlaces con años: en Facebook, en correos, en otros blogs. WordPress contesta a direcciones que nadie escribió a mano —/?p=123, /2023/05/una-entrada/, las categorías, el feed— y una mudanza que las pierde deja un rastro de errores 404. qhatu arma una tabla con todas ellas y el servidor la consulta antes que los archivos. Contra el sitio en vivo: 143 direcciones viejas, ninguna en 404 —55 que siguen siendo una página y 88 que la tabla lleva a su lugar nuevo—. Y una inventada sigue dando 404, que es lo que tiene que pasar.

Nada que hackear

Un escáner de WordPress empieza siempre igual: pregunta por las direcciones que todo WordPress tiene. Se hizo esa misma pregunta a los dos sitios, en modo pasivo —sólo pedidos de lectura a direcciones públicas, sin probar una sola contraseña—:

direcciónqué esWordPresscopia
/wp-login.phpla puerta del logincontesta404
/wp-admin/el panelcontesta404
/xmlrpc.phpla puerta clásica de la fuerza bruta en lotecontesta404
/wp-json/la APIcontesta404
/wp-json/wp/v2/usersla lista de quienes pueden entrarcontesta, con 3 nombres404
/?author=1el nombre de usuario del primer autorlo diceno
/readme.htmlla versión exactacontesta404
/wp-admin/install.phpel instaladorcontesta404
/wp-cron.phptareas que dispara cualquieracontesta404

Nueve de nueve contra cero de nueve. Además, el original anunciaba en su propio código la versión exacta de WordPress y de dos de sus plugins: exactamente lo que un atacante busca para cruzar con una lista de fallas conocidas. No es que la copia tenga esas puertas mejor cerradas: no las tiene. No hay PHP que ejecutar, ni base de datos que consultar, ni usuarios que adivinar.

Midiendo esto apareció un detalle que vale contar. La copia todavía decía «WordPress» en una etiqueta invisible del HTML, heredada del original: un escáner la leía y anunciaba un WordPress que ya no existía. El absorbedor ahora la saca.

¿Y los formularios de contacto, que en WordPress son un plugin más? En la copia los atiende una función WebAssembly que corre en el servidor con capacidades declaradas: puede guardar lo que llega, leer el reloj y mandar el aviso por correo, y nada más. No puede leer el disco; lo que no pidió no existe para ella. Los mensajes se leen en el panel, y bajan como planilla. La lupa de búsqueda que la copia puede sumar a su menú es otra función así: lee un índice que se publica junto con el sitio, y no hay servidor de búsqueda que atacar.

Y si además vende

Muchos WordPress son también una tienda, con WooCommerce. Una tienda no es un conjunto de páginas: es un catálogo con precios, variantes y existencias, y un cobro. Así que no se copia como HTML: con --as-content, qhatu lee el catálogo por la misma API pública que usa el carrito de WooCommerce y cada producto entra a la tienda propia de qhatu con su nombre, su precio exacto, su moneda, sus imágenes y una variante por cada combinación —talle, color—, con la que está agotada marcada como agotada. El precio nunca pasa por un número con coma: se guarda en centavos, y al comprar el servidor lo recalcula contra el catálogo publicado, así nadie paga lo que se le ocurra mandando otro número.

Se probó contra un WooCommerce de verdad, con los productos de ejemplo que trae el propio WooCommerce: 16 productos y 7 variantes entraron, y un instrumento que compara la tienda original contra la copia, producto por producto y variante por variante, dio iguales. Su brazo de control: después de absorber se cambió un precio y se agotó una variante en el original, y el instrumento nombró exactamente esas dos diferencias. Las reseñas de cada producto vienen con él, al pie de su página. Y con una contraseña de aplicación de WordPress —la que el propio WordPress deja crear para estos casos— viene también cuántas unidades quedan de cada producto y de cada variante: el servidor descuenta lo que se vende. Después se compró: una sudadera, al carrito, a pagar con PayPal en su entorno de pruebas, y la tienda volvió diciendo que el pedido estaba pagado, con la captura de PayPal anotada del lado del servidor.

Esa tienda está en línea, para verla y comprar con plata de mentira: tienda.gioser.net.

Y no parecen dos sitios pegados. Lo que qhatu arma —los productos, la lista, el carrito, las entradas del blog— va adentro de la cabecera, el menú, el pie, los colores y las letras del sitio original. Medido: la cabecera de una página que vino del original y la de un producto armado por qhatu dan 0 píxeles distintos. El menú del celular abre en la copia aunque el WordPress original ya esté apagado, y ya no ofrece «Finalizar compra» ni «Mi cuenta», que en la copia no existen.

Más rápido, y medido sin trampa

Cinco páginas, cinco cargas en frío de cada lado —un navegador nuevo por carga, sin caché—, alternando original y copia para que una mala racha de la red no caiga entera de un lado. Las medianas:

páginaprimer bytelo más grande pintadocarga completa
portada2,5 s → 0,9 s6,1 s → 4,9 s9,9 s → 5,9 s
página de servicio1,9 s → 0,8 s6,5 s → 3,8 s14,9 s → 5,4 s
página larga con galería2,3 s → 0,9 s11,7 s → 6,3 s22,3 s → 7,9 s
listado del blog2,4 s → 0,7 s4,5 s → 4,1 s5,1 s → 5,3 s
una entrada2,3 s → 0,8 s5,9 s → 2,5 s7,0 s → 5,2 s

Los bytes que viajan son prácticamente los mismos: es la misma página. Lo que cambia es el servidor. Y hay una salvedad que un artículo honesto tiene que hacer: los dos sitios están en servidores distintos, en lugares distintos, y la copia quedaba más cerca de donde se midió. Así que se separó la red del software. Abrir la conexión cuesta 392 milisegundos hasta el original y 179 hasta la copia; eso es distancia, no código. Descontando una ida y vuelta de cada lado, lo que queda es el trabajo de armar la página:

WordPress: ~825 ms por página saywa: ~135 ms por página
El trabajo del servidor, con la distancia de red descontada. Medido con curl, cinco pedidos de cada lado.

Y en un teléfono hay algo más. Al publicar, qhatu prepara cada imagen grande en varios anchos y el navegador elige la que le sirve: en la portada del cliente, vista a 390 píxeles de ancho, se bajan 72 % menos bytes de imagen, sin mover un píxel en una pantalla de escritorio.

Y se sigue editando, en el lugar

Una copia estática que no se puede tocar sería un museo. La de qhatu se edita desde un panel que vive en su propia dirección —nada del sitio público lo enlaza—, sobre la página misma, tal como se ve:

Captura de pantalla: a la izquierda, el panel de qhatu con un artículo abierto —fecha, imagen de portada y el cuerpo con su barra de negrita, cursiva, títulos, listas, citas, enlaces e imágenes, y el botón Guardar—; a la derecha, el mismo artículo publicado en la bitácora de gioser, con su ilustración y el título «Qué es tawasuyu»
El panel de qhatu y lo que publica, lado a lado: a la izquierda se escribe, a la derecha está el artículo tal como lo ve un lector. Es esta misma bitácora, que también arma qhatu.

Y lo que el original armó con Elementor ya no queda como un HTML que sólo se toca en el lugar: con --as-content entra como bloques de qhatu —portadas, columnas, carruseles, preguntas frecuentes— que se editan con el editor de bloques y se pintan con el tema del sitio. En el del cliente, dos de sus páginas de Elementor entraron como 22 y 12 bloques, cinco portadas con su foto de fondo y tres carruseles de diez a doce fotos, sin un solo widget que quedara sin equivalente y sin una imagen sin bajar.

Todo eso corre en saywa, el servidor web de tawasuyu. En la máquina donde vive este sitio, saywa y la forja propia del proyecto ya reemplazaron a cuatro programas: el servidor web, la forja de git, el proxy y el intérprete de PHP. Alguien escribió las dos piezas desde cero, en Rust, con una regla que se repite en todo el proyecto: lo que no se midió no se afirma.

Lo que todavía no

Cómo probarlo

La tienda de este artículo está en tienda.gioser.net, y su panel está abierto: en tienda.gioser.net/_/ cualquiera puede entrar con «Probar como autor» y editarla a gusto; lo suyo se borra a las 24 horas. El mismo qhatu arma esta bitácora y el manual de tawasuyu, y con una línea más en su configuración se vuelve una wiki: enlaces por título, la historia firmada de cada página, y dos personas que editan la misma página a la vez sin pisarse. Para tener lo mismo en una máquina propia, una VPS recién creada alcanza: qhatu server install --domain el-sitio.com deja el servidor, el panel y el certificado andando —medido sobre Debian 13 y Fedora 44, con una autoridad de certificados de prueba: la portada contesta por HTTPS a los siete segundos de tener acceso a la máquina— y qhatu absorb se trae el WordPress. qhatu vive en el repositorio de tawasuyu —git.tawasuyu.net, en un servidor propio— bajo 02_ruway/qhatu, y saywa bajo 03_ukupacha/saywa. Los instrumentos de este artículo —exposición, velocidad, píxeles y el careo de la tienda— están en scripts/qhatu-careo/: cualquiera puede correrlos contra su propio WordPress y contra su copia, y comparar.

Fondo