La pregunta de 2026 no es si WordPress puede vivir sin su tema. Puede. La pregunta es qué topología aguanta Gutenberg, vista previa, login y checkout sin convertir el origin en un endpoint PHP público.
Durante años, WordPress headless significaba que el editor perdía la vista previa, los menús se convertían en JSON a mano y cada formulario necesitaba su propia ruta REST. Esos agujeros están cerrados. WordPress 7.0 (Armstrong) salió el 20 de mayo de 2026. WordPress 7.1 sobre PHP 8.4 es el origin contra el que construimos ahora. Gutenberg entrega árboles de bloques como JSON. WPGraphQL tiene consultas persistidas. Astro 7 entrega HTML con JavaScript solo en islas. Next.js 16 entrega Partial Prerendering y Server Actions. Lo que queda es arquitectura: quién posee el contrato de datos, dónde vive la caché y cómo se le permite al frontend hablar con el origin.
Esto es un texto de arquitectura. El modelo de coste a cuatro años, CapEx y OpEx, vive en la guía TCO de headless frente a monolito. No pegues esa tabla aquí. Léela cuando defiendas un presupuesto. Lee esto cuando dibujes cajas y flechas.
WordPress deja de ser la fábrica de HTML. El directorio de temas en origin está vacío de plantillas públicas o reducido a un stub que responde 403 a GET anónimos. Los editores siguen en wp-admin. Los visitantes, nunca. El árbol de bloques es el contrato. Los CPT, taxonomías y campos ACF son de primera clase. the_content como saco HTML es un fallback para posts legacy que aún no has mapeado, no la forma objetivo.
Dos casos que medimos antes de dibujar esta caja:
- Un catálogo WooCommerce con más de 30 plugins y TTFB cerca de 1,8 s en plantillas de categoría. El tema PHP ensamblaba relacionados, reseñas, schema y un mega menú en cada petición. Pasar el catálogo a Astro 7 con lecturas GraphQL etiquetadas dejó el primer HTML en el edge. El checkout se quedó en Next.js 16 porque sesión y plugins de pago seguían necesitando un runtime por petición.
- Un sitio de marketing en Elementor que se vino abajo con el tráfico de Black Friday (ventanas de noviembre en ES, no solo el viernes). El page builder asumía que PHP pintaría cada variante. No había historia de cache tags, solo «purgar todo». Headless no salvó ese proyecto. Quitamos el builder, mantuvimos un tema acoplado y pusimos Redis más page cache delante. Desacoplar un stack de page builder es reescribir el modelo editorial, no un cambio de hosting.
Make WordPress Slack (#core-editor, #hosting) y el Block Editor Handbook son las referencias para la forma JSON, no un curso de terceros. Si un bloque no tiene salida save y solo un render.php, es un bloque solo PHP. No sobrevivirá al desacoplamiento salvo que añadas un renderer JSON.
Frontend primero: islas Astro 7 y Next.js 16
Elige el framework según cuánto de la página es documento y cuánto es aplicación. Las superficies de contenido van en Astro 7. Las que llevan sesión, carrito y filtros en tiempo real van en Next.js 16. Ambas leen el mismo origin WordPress.
Astro 7 compila páginas a HTML. El primer pintado por defecto son cero kilobytes de JavaScript. Lo interactivo (búsqueda, filtros, mini carrito, login) se hidrata como islas con client:visible o client:idle. Eso encaja con una instalación editorial: la mayoría de URLs son artículos, landings y archivos. No necesitan un runtime React en el <head>.
Next.js 16 es la llamada correcta cuando gran parte de la vista depende del estado de sesión, personalización o un árbol de carrito que no se puede prerenderizar. App Router, React Server Components y Partial Prerendering mantienen el shell estático y rellenan huecos en el edge (precio, stock, botón de pago). Las Server Actions sustituyen endpoints REST a medida para formularios, siempre que la action llame a WordPress detrás de Zero Trust y nunca exponga una cookie de admin al navegador.
Un híbrido es habitual: Astro 7 para revista, marca y docs; Next.js 16 para Mi cuenta y checkout. WordPress sigue siendo un solo origin. Dos frentes necesitan un catálogo bloque a componente compartido y un solo esquema GraphQL. Sin ese catálogo, las dos vistas divergen en un trimestre.
Faust.js y capas Next específicas de WordPress pueden acortar las cookies de preview. No son un requisito. Un endpoint fino de preview con HMAC y Draft Mode hace el mismo trabajo, y funciona contra Astro y contra Next. No dejes que el starter de un vendor elija la topología.
Cliente (navegador)
|
v
Edge (Cloudflare): HTML, assets, cache-tags
|
+-- hit: documento listo, sin PHP
|
+-- miss (preview, Mi cuenta, checkout)
|
v
Runtime frontend (Astro 7 / Next.js 16)
|
v
Gateway Zero Trust
|
v
WordPress 7.1 / PHP 8.4 / WPGraphQL
|
v
MySQL + Redis
Si el 80 por ciento de los hits de página nunca llegan a PHP, tienes una arquitectura headless. Si cada hit llega al origin «para seguir siendo dinámico», tienes un monolito más caro con un salto extra.
Cuando el desacoplamiento es la topología correcta
Desacoplar compensa cuando el contenido tiene más de un consumidor, o cuando la política de seguridad prohíbe exponer PHP a internet pública. No compensa como decoración en un sitio de marketing con tres editores que publica landings Gutenberg cada semana.
Elige headless cuando se cumpla al menos uno de estos puntos:
- La misma copia debe salir a la web, a una app, a pantallas en tienda y como fuente para asistentes internos, sin que el editor la pegue tres veces.
- El equipo frontend posee un design system en Astro o React, y WordPress no debe dictar el markup.
- wp-admin y la base de datos viven en red privada detrás de SSO. El origin público son archivos estáticos y documentos en caché.
- TTFB por debajo de 50 ms a escala global es un requisito, y aceptas que la caché vive en el edge con invalidación por tags.
Quédate en monolito cuando:
- Marketing compone landings en Gutenberg sin esperar a un desarrollador frontend por cada variante de bloque nueva.
- El checkout de WooCommerce usa extensiones que escriben HTML, shortcodes y sus propias cookies de sesión en la misma petición que la tienda (Redsys, Bizum o pasarelas locales suelen vivir ahí).
- El equipo tiene capacidad PHP y nadie es dueño de TypeScript. Dos pipelines sin dueño no es arquitectura. Es una cola de incidencias.
Un monolito moderno en PHP 8.4 con Full Site Editing, Redis y page cache no es «WordPress antiguo». Pierde en multicanal y en superficie de ataque. Gana en velocidad editorial. Elige la arquitectura contra la pérdida que realmente tienes, no contra una charla titulada headless.
Precio y propiedad a cuatro años es otra pregunta. Usa la guía TCO cuando compares CapEx del año uno con operaciones posteriores. Este artículo se detiene en topología.
El esfuerzo inicial de un desacoplamiento serio suele estar entre dos y cinco veces el de un tema acoplado bien hecho, medido en semanas de ingeniería, no en un SKU. Esa multiplicidad es esfuerzo de contrato, catálogo de bloques, preview y tags. No es una tarifa fija.
Contrato de datos: WPGraphQL, REST y consultas persistidas
WPGraphQL es la ruta de lectura de páginas ricas. REST es la ruta de escritura de eventos simples. La mezcla es deliberada, no un compromiso que «limpiarás más tarde».
Una llamada REST clásica a /wp-json/wp/v2/posts devuelve docenas de campos que un archivo no usa. Una página que necesita el post, el autor, tres relacionados y un repeater ACF se convierte en varias rondas HTTP. WPGraphQL resuelve el árbol en una sola llamada, con DataLoader colapsando búsquedas por ID en WHERE ID IN (...). Por eso GraphQL ganó en superficies WordPress desacopladas, no porque GraphQL esté de moda.
Tres reglas para el esquema:
- Expón lo que posee el editor, no lo que poseía el tema. CPT, taxonomías y campos. No
the_contentcomo saco HTML lleno de shortcodes que esperan un runtime PHP. - Consultas persistidas en producción. El cliente envía un hash, no una query arbitraria. Introspección apagada. Profundidad y complejidad máximas fijadas. Sin eso, GraphQL es una ventana abierta a la base de datos.
- Cache tags en la respuesta.
post-1425,tax-tema-headless,author-8,lang-es. Sin tags vacías todo el edge cada vez que alguien corrige una errata.
REST se queda con los trabajos en los que GraphQL es malo: webhooks entrantes, eventos de pago, posts de formularios desde un endpoint fino y CRUD desde herramientas internas. Esos endpoints se autentican con App Passwords o JWT cortos, nunca con una application password infinita metida en un repo frontend.
<?php
declare(strict_types=1);
add_action('graphql_register_types', static function (): void {
register_graphql_field('Post', 'heroKicker', [
'type' => 'String',
'description' => 'Kicker corto sobre el hero, propiedad de redacción.',
'resolve' => static fn ($post) => get_post_meta($post->databaseId, 'hero_kicker', true) ?: null,
]);
});
Si un campo no se puede describir en una frase para un editor, no pertenece al esquema público.
En proyectos ES que hemos auditado, el fallo típico no era «GraphQL lento». Era un esquema que exponía rendered HTML más un campo ACF de NIF «para el pie legal», y luego el frontend olvidaba renderizar ese campo en el HTML cacheado. El contrato sin consumidor visible es papel mojado.
Gutenberg como JSON, no como saco de HTML
El default de 2026 es el mapeo bloque a componente. WordPress serializa cada bloque con name, attributes e innerBlocks. El frontend tiene un diccionario: core/paragraph se convierte en <Prose>, core/image en <Figure>, acf/pricing-table en <PricingTable>. Los nombres de bloque desconocidos renderizan un fallback visible en staging y un nodo vacío en producción, con una línea de log. El silencio es cómo empieza el drift de diseño.
No envíes the_content y esperes que React «simplemente renderice el HTML». Shortcodes, do_shortcode, markup de Gravity Forms y widgets de Elementor asumen PHP. Se verán correctos en la preview de wp-admin contra el tema viejo y mal en el sitio Astro. Esa es la muerte de la confianza editorial en dos semanas, con otro disfraz.
Mantén un solo catálogo. Si la revista es Astro 7 y el checkout es Next.js 16, ambos importan el mismo módulo de mapeo. Un bloque nuevo que solo existe en un frontend es un bug de producto, no un nice to have.
El Block Editor Handbook y los tickets de trac alrededor de parse_blocks / serialize_blocks son la fuente de verdad del árbol. Los kits de terceros «Gutenberg to React» se quedan viejos en cuanto core añade un atributo de bloque.
En WordCamps en España (Madrid, Barcelona, Valencia en años recientes) la conversación que se repite es la misma: el equipo de diseño pide 40 bloques «como el tema de siempre». El equipo frontend puede mantener doce con tests. Doce bloques mapeados ganan a ochenta bloques que nadie ha cableado. Limita la paleta. Esa es la restricción real del desacoplamiento, y pertenece al presupuesto de esfuerzo, no a un eslogan de libertad.
Las imágenes pasan por el pipeline del frontend (Astro Assets o next/image) a AVIF con anchos que encajan con el layout. WordPress guarda el original. El origin no debe servir hero-4000px.jpg a un móvil en una red 4G de AVE.
LSSI e identificación del prestador en un storefront Astro
En España, un storefront desacoplado no es solo un problema de caché. Es un problema de documento público. La LSSI (Ley 34/2002 de servicios de la sociedad de la información) exige que el prestador se identifique: razón social o nombre, NIF, domicilio y datos de contacto. Ese texto tiene que estar en el HTML que el edge sirve al público, no solo en un campo ACF que el editor ve en wp-admin.
El fallo clásico en proyectos headless ES es este: el pie legal vive en un widget del tema PHP o en un bloque que nadie mapeó. El frontend Astro 7 entrega un documento limpio, rápido y sin NIF. El inspector mira el HTML cacheado en Cloudflare y no encuentra la identificación del prestador. wp-admin tiene los datos. El visitante, no. La LSSI mira el servicio de la información que se presta al público, no el back office.
Consecuencias de arquitectura:
- Trata la identificación LSSI como contenido de contrato. Un campo tipado en el esquema (
legal.entityName,legal.nif,legal.address,legal.contactEmail) entra en el layout compartido (footer, página de aviso legal, a veces cabecera en checkout). Si el campo falta, el build de staging falla. No es un copy pegado a mano en tres plantillas. - El HTML estático del edge debe llevarlo. Si solo una isla React hidratada pinta el NIF tras
client:visible, el primer documento (y el que ven crawlers y herramientas de inspección) puede salir incompleto. Preferimos el NIF en el HTML compilado por Astro, no en una isla. - Cookies y consentimiento son otra superficie. El banner de consentimiento (cookies de analítica, remarketing, preferencias) suele ser una isla. Eso está bien para la UI. Lo que no está bien es que el propio mecanismo de registro del consentimiento dependa de hidratar JavaScript para existir en el DOM. La AEPD mira qué se ha informado y qué se ha consentido. Un HTML estático sin aviso, más una isla que «aparece después», es un hueco. Diseña el aviso mínimo en HTML y deja la interacción (aceptar, rechazar, configurar) en la isla.
- Logs orientados a la AEPD. Quién cambió el texto legal, cuándo se publicó, qué versión del documento estaba en caché en un instante, qué tags se purgaron. Eso no es un dashboard de marketing. Es trazabilidad si hay un requerimiento. Propaga
traceparenty guarda el hash de la consulta persistida que alimentó el footer legal, igual que guardarías el hash de un artículo.
No confundas esta capa con obligaciones fiscales de facturación electrónica. Verifactu, SII u otros regímenes de factura son un problema de API y de origen de datos contables. Aquí hablamos de identidad legal en documentos cacheados. Mezclar ambos en el mismo sprint es cómo se hincha el alcance sin cerrar ninguno.
En un catálogo Astro con checkout en Next, el footer legal debe ser el mismo módulo importado por ambos frentes. Un NIF distinto en revista y en Mi cuenta es un incidente de cumplimiento, no un detalle de CSS. El servicio comercial de WordPress headless incluye ese cableado cuando el origin está en España o presta servicios a residentes en España; no es un «extra de copy».
Vista previa sin romper la caché de producción
La vista previa es una feature con presupuesto de sprint. No es una casilla en el panel de hosting.
Flujo que entregamos:
- El editor pulsa Vista previa en
wp-admin. - WordPress firma un token HMAC de corta vida ligado a post ID, user ID y caducidad.
- El navegador abre la ruta
/previewdel frontend con ese token. - El runtime del frontend bypasea la caché anónima, pide el borrador por WPGraphQL con el token y renderiza el mismo árbol de componentes que producción.
- La caché de producción de la URL en vivo no se toca.
Si la preview pide el permalink publicado en lugar del borrador, los editores «arreglarán» copy que ya está publicado. Si la preview comparte la clave de caché anónima, un borrador se filtra al siguiente visitante. Ambos bugs son peores que no tener preview.
Draft Mode en Next.js y una ruta Astro no-store son detalles de implementación. El contrato es: firmado, con tiempo limitado, acotado al post y aislado de la clave de caché pública.
Sin preview fiable, el headless muere en redacción. Lo hemos visto en equipos de revista digital en Madrid y Barcelona: a la segunda semana, los editores publican a ciegas o piden volver al tema PHP «solo para mirar». Esa petición es un veredicto de arquitectura, no de gusto.
Cache tags en el edge
El edge es el almacén de HTML. El origin es la fuente de invalidación.
Al publicar, actualizar o borrar, WordPress dispara un webhook con los tags que cambiaron. Cloudflare (o el equivalente) purga esos tags. Una errata en el post 1425 purga post-1425 y quizá tax-noticias. No purga la home de cada locale.
Stale-while-revalidate está permitido para documentos anónimos. No lo está para preview, carrito o Mi cuenta. Esas rutas son cache-bypass por construcción.
No alojamos el frontend «en Vercel o Netlify» como elección de marca. Ponemos el HTML en Cloudflare porque cache tags y HTML son el mismo producto. Una plataforma que solo puede purgar por URL o por «todo» te empuja otra vez a rebuilds completos. Los rebuilds completos son cómo los proyectos headless se vuelven más lentos que el tema PHP que sustituyeron.
Para números de rendimiento en tienda, ver headless WooCommerce en Astro (rendimiento). Este artículo se queda en el modelo de invalidación.
SWR muestra el documento viejo al instante y trae el nuevo en segundo plano. Para noticias con marca de tiempo visible puedes bajar s-maxage. Para landings que cambian semanalmente, puedes dejar vivir el documento. Es política editorial, no una cabecera mágica.
Madrid o Valencia frente a una base en Fráncfort da igual mientras el hit se detenga en un PoP en España. Madrid frente al origin en cada petición HTML es la latencia que la gente llama «headless es lento».
Autenticación detrás del origin
El origin público no habla cookies de admin. wp-admin vive detrás de Zero Trust (Cloudflare Access u SSO equivalente). Las application passwords del frontend viven en el worker o en el servidor, no en un env público que viaja al navegador.
Los plugins JWT con vida infinita son una trampa. Si usas JWT, rota, ata a audience y mantén la clave privada fuera del bundle de Astro. App Passwords acotadas a un usuario bot (headless-read) son más simples para GraphQL de solo lectura.
Los rate limits van en el gateway, no en un mu-plugin que paga cada petición. El gateway ve hashes de GraphQL. El mu-plugin ve PHP. Prefiere el gateway.
wp-login.php y /xmlrpc.php no están en el hostname público. Passkeys o SSO hacia admin, no «contraseñas fuertes» como único control. En equipos ES con proveedores externos de marketing, el patrón recurrente es una application password compartida en un Notion: eso es un incidente esperando fecha. Un bot por entorno, secreto en el almacén del edge, rotación al cambiar de persona.
Observabilidad a lo largo de la cadena
Un miss headless son tres sistemas: edge, runtime frontend, WordPress. Sin contexto de traza depurarás el equivocado.
Propaga W3C traceparent desde el edge, por el fetch del frontend, hasta WPGraphQL. Registra el conjunto de cache tags, el hash de la consulta persistida y el status del origin. Cuando LCP empeora, quieres saber si el documento fue un cache hit, un render de frontend o un miss PHP, no «la web se siente lenta».
OpenTelemetry basta. No inventes un cuarto dashboard.
En incidencias con la AEPD o con un cliente que pide «qué se sirvió el martes a las 11», esa traza es la diferencia entre una respuesta en horas y una reconstrucción a ciegas. Guarda también qué versión del bloque legal estaba en el documento (ver sección LSSI). Cumplimiento y rendimiento comparten el mismo cableado de logs.
Tests de contrato en CI
Cada cambio de esquema GraphQL es un cambio de frontend. CI debe fallar si:
- falta un hash de consulta persistida
- un nombre de bloque en los fixtures no tiene componente
- un campo requerido pasó a nullable
- la introspección está encendida en la config de producción
- faltan los campos LSSI requeridos en el layout compartido
Ejecutamos esas comprobaciones en pull request, contra un origin de staging restaurado desde un dump sanitizado de producción. Un esquema que solo existe en el localwp de un desarrollador no es un contrato.
E2E de preview: un borrador en WordPress debe verse con token válido e invisibilizarse sin él. E2E de caché: publicar el post 1425 no debe 404-ear la home. Sale más barato que descubrirlo en redacción un lunes por la mañana.
Qué construye WPPoland
Montamos WordPress headless igual que headless WooCommerce: el CMS se queda como origin, el frontend se entrega aparte y la vista previa es una feature de primera clase.
En la práctica:
- Un contrato REST o WPGraphQL documentado antes de que arranque el frontend, para que redacción sepa qué campos, taxonomías y esquemas de bloque están cableados.
- URLs de preview que firman un token de borrador en WP y resuelven por la ruta draft del frontend, incluyendo ACF y contenido de bloques Gutenberg.
- Un mapa de redirects producido desde el sitio existente antes del lanzamiento, para que las URLs legacy aterrizen en la estructura nueva y Search Console no muestre un pico de regresión.
- Un plan de rollback: el tema PHP sigue desplegable hasta que el nuevo frontend haya aguantado tráfico de producción al menos un ciclo completo de publicación.
- Identificación LSSI en el HTML público cuando el prestador opera bajo normativa española, cableada al esquema y al layout, no pegada a mano en el footer.
Si el discovery encuentra poco volumen editorial, un stack de plugins que depende del frontend PHP, o cero capacidad de ingeniería JS, lo decimos y recomendamos seguir acoplados. Headless es una herramienta, no un símbolo de estatus. La superficie comercial es el servicio WordPress headless. La conversación de presupuesto es la guía TCO.
Para un cutover de acoplado a headless, empieza por migración de sitio a Astro y Next.js o la página de desarrollador Astro. El spike es una semana: tres plantillas de más tráfico, un borrador con preview, una fila de redirect. La fricción de esa semana es la fricción que tendrías durante un año.
Conclusión
Desacopla cuando el contenido tiene más de un consumidor, cuando PHP no debe ser público o cuando el equipo frontend ya posee el design system. Quédate acoplado cuando Gutenberg es la fábrica de landings y el checkout sigue escribiendo HTML en PHP.
WordPress 7.1 sobre PHP 8.4 es un origin sólido. Astro 7 y Next.js 16 son frentes sólidos. La arquitectura es el contrato entre ellos: consultas persistidas, mapeo de bloques, preview HMAC, cache tags, Zero Trust, e identificación del prestador en el HTML que realmente se sirve. Falla uno de esos y no has construido headless. Has construido un monolito más lento con saltos extra.
Si la semana de spike sale limpia (tres plantillas, un borrador con preview, una fila de redirect) tienes evidencia, no una diapositiva. Si no sale limpia, quédate acoplado y gasta el dinero en Redis, page cache y borrar plugins que pintan HTML en cada petición. Eso también es arquitectura. Solo es honesta con el equipo que tienes.





