santiagomarquez.online
Arte y portfolio · 2026

Sacar un sitio de WordPress sin perder el panel del cliente

Gisel Rosso — muralista

Servicios
Migración a CMS headlessDesarrollo a medidaE-commerceAuditoría y mejoras SEO
Stack
AstroReactSanityTailwindNetlifyMercado PagoPayPal
Ver giselrosso.com →
Captura de giselrosso.com

El problema

Gisel es muralista y tiene obra en quince países. Su sitio ya corría sobre un front moderno —Astro con islas de React, animaciones y pagos integrados— pero el contenido vivía en un WordPress aparte, con Elementor y WooCommerce.

Eso significaba un hosting que alguien tenía que pagar y mantener, plugins que actualizar, y un panel pensado para desarrolladores, no para una artista que solo quiere subir fotos de un mural nuevo.

El pedido era claro: que ella pueda administrar su sitio sola y que no haya un servidor del que depender.

Lo que encontré al revisar

Antes de proponer nada audité la dependencia real con WordPress. Era más profunda de lo que el código sugería a primera vista: 53 referencias repartidas en cinco caminos distintos.

Tres eran serias:

45 imágenes enlazadas directo al WordPress. No pasaban por ninguna API: eran URLs a wp-content/uploads escritas a mano en los componentes. El día que ese hosting se apagara, se rompían.

Dos galerías se extraían parseando HTML. Las secciones de fachadas e interiores —165 fotos— no salían de la API de contenido: una función buscaba data-thumbnail="..." con expresiones regulares dentro del HTML renderizado por Elementor. Cualquier cambio de plantilla o de versión las vaciaba.

El visor de galería pedía las imágenes en vivo. Aunque la página estuviera pre-construida, cuando alguien abría una obra el navegador le pegaba a WordPress, una petición por foto. Si ese servidor estaba lento, la galería quedaba cargando.

Había además una señal de que esto ya fallaba: el código tenía manejo explícito para cuando el CDN del hosting bloqueaba la API. Y como el error se tragaba en silencio, el sitio se construía con la galería vacía sin que el build fallara.

Qué construí

Reemplacé WordPress por Sanity como back de contenido, manteniendo el front que ya existía.

  • Esquema a medida con los campos que Gisel realmente usa: obra, producto, galería y pedido. Nada de los cuarenta menús que no necesitaba.
  • Panel propio, con el menú armado en cuatro secciones y textos en español.
  • Script de migración idempotente y retomable: 27 obras, 4 productos, 5 galerías y 712 imágenes (163 MB), con caché de archivos ya subidos para poder cortarlo y seguir.
  • Publicación automática: un webhook de Sanity dispara el build en Netlify cuando ella publica. De apretar “Publicar” a verlo en el sitio pasan unos 60 segundos.
  • Los pedidos pasaron a Sanity, manteniendo la firma de la función anterior para no tocar los endpoints de Mercado Pago ni PayPal. De paso, el precio ahora sale del CMS en vez de confiar en lo que manda el navegador.

Decisiones técnicas

Mantuve las interfaces. La capa nueva expone los mismos tipos que la vieja, así que los componentes del sitio no se tocaron. El cambio quedó contenido en cuatro archivos en lugar de repartido por todo el proyecto.

Las descripciones pasaron a texto enriquecido. Antes eran HTML crudo de WooCommerce. Ahora Gisel las edita con un editor normal: negrita, cursiva, enlaces. No tiene que ver una etiqueta nunca.

El panel vive aislado. Las dependencias del CMS chocaban con las del sitio, así que lo separé en su propia carpeta con su propio package.json. Si las hubiera mezclado, la instalación en Netlify fallaba y rompía el deploy de producción.

Maté el scraper. Las galerías de fachadas e interiores pasaron a ser documentos editables. Es lo que más valor le dio a ella: eran justamente las dos secciones que no podía tocar de ninguna forma razonable.

Lo que apareció en el camino

Tres fallas que no daban error y que vale la pena contar, porque son el tipo de cosa que convierte una migración “exitosa” en un problema de meses.

Los IDs de galería eran texto, no números. WordPress guardaba '1312' con comillas. Mi índice de imágenes estaba armado por número, así que ninguna búsqueda encontraba nada: las 469 fotos de galería se perdían y el script terminaba informando éxito. El código viejo nunca lo notó porque interpolaba el ID en una URL, donde da lo mismo.

Un punto en el identificador dejaba los documentos invisibles. Los creé como obra.batalla-de-munda. Sanity trata el punto como separador de espacio privado: con credenciales se veían los 36 documentos, sin credenciales ninguno — que es exactamente como lee el sitio. Lo confuso fue que las imágenes sí se veían, porque sus identificadores no llevan punto. Lo confirmé con dos documentos idénticos salvo el ID, uno con punto y otro con guion.

El build publicaba contenido viejo. El webhook dispara la reconstrucción apenas se publica, así que el build arrancaba segundos después del cambio y leía del CDN, que todavía servía la versión anterior. El deploy figuraba como correcto y el cambio no aparecía. Era intermitente —a veces el CDN llegaba a tiempo— que es el peor modo de falla posible: habría hecho dudar a Gisel de si guardó bien, en vez de sospechar del sistema.

La parte de SEO

Al revisar la indexación apareció algo que ya estaba pasando en producción: Google mostraba el sitio en inglés.

El Layout tenía un redirect del lado del cliente que mandaba / a /en cuando el idioma del navegador empezaba con “en”. Googlebot rastrea habitualmente como en-US, se comía el redirect, y terminó indexando la versión inglesa como si fuera el sitio.

De paso corregí dos cosas más:

  • Las 54 fichas de obra no estaban en el sitemap. Se servían en el momento, y el generador solo incluye páginas pre-construidas. El contenido más rico del sitio era invisible. Pasaron a pre-construirse: el sitemap fue de 30 a 82 URLs.
  • Faltaba hreflang. El sitio tenía versiones en español e inglés pero nada se lo decía a Google, así que competían entre sí.

El resultado

  • Sin hosting de WordPress: un gasto y una tarea de mantenimiento menos, para siempre.
  • Gisel administra su sitio sola, con un panel hecho para lo que ella hace.
  • De publicar a estar en vivo: 60 segundos, verificado de punta a punta.
  • Cero referencias a WordPress en todo el sitio construido.
  • 82 URLs indexables donde antes había 30.

El contenido y las 712 imágenes quedaron verificados uno a uno contra el original antes de dar la migración por terminada.

El sitio, por dentro

Portada del sitio de Gisel Rosso con sus obras destacadas
La portada y el carrusel de obras destacadas.
Galería de murales de Gisel Rosso y su sección de presentación
Las obras: contenido que la artista carga y ordena desde su panel.
Contacto

¿Hablamos?

Si querés una web para tu negocio o buscás un desarrollador para sumar a tu equipo, elegí el tipo de consulta y contame qué necesitás.

Santiago Márquez, desarrollador web
Santiago Márquez Desarrollador Web Reconquista

Contame sobre tu proyecto

Campos obligatorios

¿Qué necesitás?
¿Hablamos?