WP Headless Mode v1.3.1
Plugin para WordPress que convierte una instalación estándar en un CMS headless optimizado. Requiere PHP 8.0+ y WordPress 6.0+.
¿Qué hace este plugin?
WP Headless Mode transforma WordPress en un backend API-first, desacoplando completamente el frontend del servidor. Al activarlo:
- Todas las URLs del frontend devuelven JSON 404 en vez de HTML
- Los plugins de renderizado (Elementor, page builders, caché HTML) se omiten en requests de API, ahorrando 8–30 MB de RAM por request
- La REST API nativa queda endurecida con CORS granular, rate limiting y headers de seguridad
Instalación
- Copia la carpeta
wp-headless-modea/wp-content/plugins/ - Activa el plugin desde Plugins → Plugins instalados
- Ve a Headless Mode → Configuración y activa el modo headless
- Configura los orígenes CORS permitidos con la URL de tu frontend
Arquitectura
Flujo de arranque
plugins_loaded
└── wp_headless_mode_init()
├── WP_Headless_Core::init() → hooks de template y features
├── WP_Headless_Optimizer::init() → hooks de plugins y cron
├── WP_Headless_API_Enhancer::init() → hooks REST
└── WP_Headless_Admin::init() → (solo is_admin()) menú y AJAX
Módulo: Headless Core
Archivo: includes/class-headless-core.php
Responsable de bloquear el frontend y eliminar ruido de WordPress.
| Acción | Hook | Descripción |
|---|---|---|
| Bloquea frontend | template_include (PHP_INT_MAX) | Devuelve headless-frontend.php → JSON 404 |
| Vacía assets del theme | wp_enqueue_scripts (PHP_INT_MAX) | Elimina todos los scripts y estilos en frontend |
| Desactiva XML-RPC | xmlrpc_enabled | Stub que responde 403 JSON |
| Desactiva embeds | init | Elimina rutas, filters y head links de oEmbed |
| Desactiva emojis | init | Elimina emoji.js y DNS prefetch de s.w.org |
| Limpia <head> | init | Elimina generator, shortlink, feed links, REST link |
| Añade header | send_headers | X-WP-Headless: 1 en todas las respuestas |
Respuesta a requests de frontend bloqueados
{
"error": "not_found",
"message": "This WordPress installation operates in headless mode...",
"api": {
"rest": "https://tu-sitio.com/wp-json/wp/v2/",
"health": "https://tu-sitio.com/wp-json/headless/v1/health"
}
}
Módulo: Optimizer
Archivo: includes/class-headless-optimizer.php
Filtrado de plugins en REST
En cada request a la REST API, el Optimizer modifica la opción active_plugins en memoria para excluir plugins de frontend. Plugins como Elementor, WP Rocket o Jetpack nunca llegan a cargar en requests de API, ahorrando entre 8–30 MB de RAM por request.
// Plugins excluidos automáticamente en requests REST:
elementor, elementor-pro, beaver-builder-plugin,
wp-super-cache, w3-total-cache, wp-rocket,
litespeed-cache, autoptimize, wp-fastest-cache, jetpack
frontend en los overrides manuales también se excluyen. El filtro actúa sobre option_active_plugins con prioridad 1, antes de que los plugins registren sus hooks.
Módulo: Plugin Classifier
Archivo: includes/class-plugin-classifier.php
| Clasificación | Significado | Impacto |
|---|---|---|
| headless-ready | Diseñado para headless (WPGraphQL, ACF, JWT...) | Ninguno |
| admin-only | Solo actúa en wp-admin (Wordfence, UpdraftPlus...) | Ninguno |
| api-aware | Tiene REST API pero también carga assets en frontend | Bajo |
| frontend | Renderizador HTML, incompatible con headless | Alto |
| unknown | Sin clasificación conocida, requiere revisión manual | Medio |
Módulo: API Enhancer
Archivo: includes/class-api-enhancer.php
Headers de seguridad en todas las respuestas REST
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), camera=(), microphone=()
Cache-Control: no-store, no-cache, must-revalidate
X-Headless-Mode: true
X-Response-Time: 42ms
Módulo: Admin Panel
Archivo: admin/class-headless-admin.php
| Sección | URL | Descripción |
|---|---|---|
| Dashboard | ?page=wp-headless-mode | Estado, stats, endpoints activos, optimización DB |
| Plugins | ?page=wp-headless-plugins | Tabla filtrable con clasificación y override manual |
| Configuración | ?page=wp-headless-settings | Todos los toggles y configuración |
| Theme | ?page=wp-headless-theme | Instalar placeholder theme y limpiar themes innecesarios |
Eliminación del menú Apariencia
Cuando el modo headless está activo, el menú Apariencia de WordPress se elimina automáticamente del panel de administración. Esto incluye todos sus submenús: Themes, Customizer, Widgets, Menús y Theme Editor.
Gestión del theme placeholder
WordPress requiere un theme activo internamente aunque el frontend esté bloqueado. La sección Theme del menú permite instalar el placeholder mínimo (2 archivos) y eliminar todos los themes innecesarios.
Referencia: Audit API
Base: /wp-json/headless/v1/ — Requieren usuario con capacidad manage_options.
Parámetros opcionales: classification (filtro por tipo) · active_only=true
{ "classification": "admin-only" }
{
"status": "ok",
"headless": true,
"version": "1.3.1",
"wp_version": "6.7",
"php_version": "8.2.0",
"timestamp": "2026-03-31T12:00:00+00:00"
}
Autenticación
Cuando Requerir auth en REST API está activo, todos los endpoints requieren autenticación. WordPress soporta nativamente Application Passwords (desde WP 5.6):
# Con Application Password (usuario:app-password en base64)
curl https://tu-sitio.com/wp-json/wp/v2/posts \
-H "Authorization: Basic dXN1YXJpbzpwYXNz"
Rate Limiting
- Sin autenticación:
api_rate_limit_maxrequests/hora por IP (default: 100) - Autenticado: 5× el límite base
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Window: 3600
CORS
Configura los orígenes desde Configuración → Orígenes CORS permitidos. Un origen por línea. Vacío = acepta cualquier origen (*).
Base de datos
wp_headless_ratelimit
ip VARCHAR(45)
endpoint VARCHAR(255)
hits INT
window_start DATETIME INDEX
PRIMARY KEY (ip, endpoint)
Settings
Guardadas en wp_options bajo la clave wp_headless_settings.
Auditoría de plugins
Para sobrescribir una clasificación usa el dropdown en Plugins o la API:
curl -X POST https://tu-sitio.com/wp-json/headless/v1/plugins/elementor/classify \
-H "Cookie: wordpress_logged_in_..." \
-d '{"classification": "frontend"}'
Optimización de autoload
Marca como autoload=no los siguientes patrones de wp_options:
widget_% → Configuraciones de widgets
sidebars_widgets → Sidebar configuration
%_transient_% → Transients
elementor% → Opciones de Elementor
fl_% → Opciones de Beaver Builder
theme_mods_% → Modificaciones del theme activo
wp_options.
Limitaciones conocidas
El bootstrap de WordPress siempre cargará ~200 archivos PHP y ejecutará la query de wp_options antes de que cualquier plugin pueda intervenir. Para reducir este overhead:
- Bedrock (Roots.io) para una estructura más limpia
- Nginx + FastCGI cache para cachear respuestas de API completas
- Redis Object Cache para cachear el bootstrap y queries de WP
frontend registra Custom Post Types o meta fields que necesitas en la API, excluirlo en REST lo romperá. Verifica qué CPTs registra antes de marcarlo como frontend.
Acerca del autor
Javier Rivera es Full Stack Developer con más de 25 años de experiencia construyendo soluciones digitales, habiendo evolucionado desde programador hasta liderazgo técnico y arquitectura de software.
Especializado en arquitecturas headless, e-commerce (WordPress, WooCommerce, Shopify, Magento), integraciones empresariales y desarrollo de APIs. Ha trabajado en proyectos en más de 6 países para clientes en educación, farmacéutica, retail, finanzas y gobierno.
| Área | Tecnologías |
|---|---|
| Backend | PHP · Node.js · Python · FastAPI |
| Frontend | JavaScript · Next.js |
| Infraestructura | Docker · AWS · Azure · DigitalOcean |
| Herramientas | Claude · GitHub Copilot · n8n |
Más información en jjrc.dev · hola@jjrc.dev