WP WordPress Intermedio

Headless Starter Kit — Guía completa

Instalar, configurar y desplegar Headless Starter Kit: plugin WordPress + starter Next.js 15 llave en mano para pasar WooCommerce a headless.

Actualizado Versión del módulo 1.0.0

Esta guía cubre la instalación, configuración y uso completo de Headless Starter Kit — el plugin WordPress que convierte tu tienda WooCommerce en un comercio headless, acompañado de un starter Next.js 15 llave en mano.

A quién se dirige esta guía. Desarrolladores, agencias o comerciantes técnicos que quieren pasar un WooCommerce existente a headless sin reinventar autenticación, carrito y checkout. Debes sentirte cómodo con la línea de comandos, Node.js y algo de configuración de servidor si eliges Hetzner.

Visión general

Headless Starter Kit se presenta como dos entregables en una sola compra:

  1. El plugin WordPress (ZIP subido vía /wp-admin/plugins.php) que expone del lado backend: autenticación JWT, API de carrito, puente de checkout, endpoint de configuración público, webhooks ISR y CORS estricto.
  2. El starter Next.js 15 (ZIP descargable desde el admin WordPress una vez el plugin activado y configurado) que contiene un proyecto Next.js completo con páginas home, listado, ficha producto ISR, carrito, checkout, login, registro y área de cliente — variables de entorno ya pre-rellenadas con tus URLs y secretos.

La arquitectura es deliberadamente simple: tu WooCommerce sigue siendo la fuente de verdad (productos, pedidos, stock, pagos), y Next.js consume la API REST mediante rutas proxy seguras. Sin duplicación de base de datos, sin réplica que gestionar.

Requisitos

Lado WordPress

  • WordPress 6.4 o superior
  • WooCommerce 8.0 o superior (probado hasta 9.5)
  • PHP 8.1 o superior
  • Enlaces permanentes configurados en Nombre de la entrada (no en Simple)
  • HTTPS activo (imprescindible para cookies httpOnly y autenticación en producción)
  • Un par de claves WooCommerce REST con lectura-escritura (generadas en WooCommerce → Ajustes → Avanzado → REST API)

Lado frontend Next.js

  • Node.js 20 o superior (recomendado: gestionar versiones con nvm)
  • Alojamiento compatible con Node: Vercel, Hetzner VPS, Netlify, Railway o cualquier servidor capaz de ejecutar Node 20+

El alojamiento compartido clásico (o2switch, OVH compartido, etc.) no es adecuado para alojar el frontend Next.js, que requiere un runtime Node persistente. El plugin WordPress, en cambio, funciona en cualquier alojamiento compatible con WP.

Instalación del plugin WordPress

  1. Desde el back-office de WordPress, ve a Plugins → Añadir nuevo → Subir plugin.
  2. Selecciona el archivo dfheadlessstarterkit.zip, luego haz clic en Instalar ahora.
  3. Haz clic en Activar plugin.
  4. Aparece un nuevo menú Headless Kit en la barra lateral izquierda, con tres pestañas: Ajustes, Diagnósticos, Descargar starter.

Al activar, el plugin genera automáticamente un secreto JWT y un token de revalidación aleatorios. Puedes regenerarlos en cualquier momento desde los ajustes.

Configuración

Abre Headless Kit → Ajustes. Cada sección es independiente y puede modificarse sin reiniciar nada.

URL del frontend

Introduce la URL pública completa de tu aplicación Next.js, sin barra final. Ejemplo:

https://shop.ejemplo.com

Esta URL sirve para tres cosas: construir los webhooks ISR, alimentar la variable NEXT_PUBLIC_SITE_URL del starter entregado, y validar el origen CORS por defecto.

Secreto JWT y token de revalidación

Se utilizan dos secretos:

  • Secreto JWT — firma los tokens de acceso y refresh. Al menos 32 caracteres. Nunca lo compartas.
  • Token de revalidación — enviado en la cabecera Authorization: Bearer … de los webhooks ISR. Debe ser idéntico a la variable REVALIDATE_TOKEN del lado Next.js.

Un botón Regenerar junto a cada campo produce un secreto aleatorio criptográficamente sólido vía crypto.getRandomValues.

Tras regenerar el secreto JWT, todos los tokens de acceso y refresh existentes quedan inválidos. Los usuarios tendrán que volver a iniciar sesión. Avísales o hazlo fuera de horas punta.

Modo carrito: ¿JWT o servidor?

La elección se hace mediante un botón radio en los ajustes.

Modo JWT (por defecto, recomendado)

El carrito completo se serializa en un token firmado HS256 y se devuelve mediante la cabecera X-DFHSK-Cart. No se almacena ningún dato del lado WordPress. Ideal para:

  • Despliegues en Vercel edge, Cloudflare, o multi-instancia
  • Tiendas de alto tráfico donde evitar la base de datos en cada llamada es una ganancia neta
  • Configuraciones donde WordPress es puramente API y no necesita sesiones

Modo servidor (WC_Session)

El carrito vive en la tabla WC_Session nativa de WooCommerce. Preferible si:

  • Usas extensiones WooCommerce que se enganchan al carrito (WooCommerce Subscriptions, Dynamic Pricing, plugins YITH, etc.)
  • Quieres conservar la lógica de sesión nativa de WooCommerce (recuperación nativa de carritos abandonados, cross-sell del lado servidor, etc.)

Orígenes CORS

Una lista blanca estricta de orígenes autorizados a llamar la API. Un origen por línea, formato completo https://…. Se admiten comodines de subdominios:

https://shop.ejemplo.com
https://preview.ejemplo.com
https://*.previews.ejemplo.com
http://localhost:3000

Añade http://localhost:3000 durante el desarrollo, luego quítalo en producción.

Eventos ISR

Cinco casillas indican qué eventos de WordPress disparan un webhook ISR hacia Next.js:

  • Productossave_post_product, woocommerce_update_product
  • Categorías — creación, actualización, eliminación de términos de la taxonomía product_cat
  • Pedidos — cambios de estado (útil para refrescar la página de cuenta)
  • Páginassave_post_page
  • Cupones — creación y actualización de códigos promocionales

Un textarea Rutas a revalidar te permite definir con precisión qué rutas Next.js se revalidan para cada evento (por defecto, el plugin deduce inteligentemente las rutas afectadas).

Diagnósticos

Headless Kit → Diagnósticos. Once controles automáticos se ejecutan cada vez que se muestra la página:

  1. WooCommerce activo — la clase WooCommerce está disponible
  2. Enlaces permanentes correctos — la estructura no es Simple
  3. REST API accesible/wp-json/ responde 200
  4. HTTPS activois_ssl() devuelve true
  5. WPGraphQL detectado — solo informativo, no bloqueante
  6. Secreto JWT definido — al menos 32 caracteres
  7. URL del frontend configurada — no vacía y formato URL válido
  8. Orígenes CORS definidos — al menos un origen
  9. Token de revalidación definido — al menos 24 caracteres
  10. Claves WooCommerce REST — el plugin detecta un par consumer_key/consumer_secret activo
  11. Modo carrito legible — el almacenamiento elegido funciona

Cada control muestra verde (OK), naranja (advertencia, no bloqueante) o rojo (bloqueante). Resuelve todo lo rojo antes de pasar a producción.

Descargar y lanzar el starter Next.js

Una vez rellenados los ajustes y los diagnósticos en verde, abre Headless Kit → Descargar starter. Haz clic en el botón grande Descargar starter Next.js.

El ZIP entregado es un proyecto Next.js 15 completo, generado sobre la marcha con tus URLs y secretos ya inyectados. Placeholders reemplazados en la generación:

  • {{SITE_URL}} → URL de tu WordPress
  • {{FRONTEND_URL}} → URL del front configurada
  • {{REVALIDATE_TOKEN}} → tu token de revalidación
  • {{CURRENCY}} → moneda WooCommerce
  • {{SITE_NAME}} → título del sitio
  • {{LOCALE}} → locale WordPress (es, fr, en, etc.)

El archivo .envtmpl se renombra a .env.example en la generación.

Variables de entorno a completar manualmente

Algunos valores no pueden recuperarse automáticamente — debes añadirlos al archivo .env (creado desde .env.example):

WOO_REST_CONSUMER_KEY=ck_xxxxxxxxxxxxxx
WOO_REST_CONSUMER_SECRET=cs_xxxxxxxxxxxxxx
SESSION_PASSWORD=tu-contrasena-de-32-caracteres-minimo

Genera un SESSION_PASSWORD sólido:

node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

Desarrollo local

npm install
cp .env.example .env
# Edita .env con tus secretos que faltan
npm run dev

El front está disponible en http://localhost:3000. Añade esta URL a los orígenes CORS del lado WordPress durante el desarrollo.

Despliegue en Vercel

npx vercel link
npx vercel env pull .env.production
npx vercel deploy --prod

Después configura todas las variables de entorno en el dashboard de Vercel (Project → Settings → Environment Variables). El archivo vercel.json entregado fija la región en cdg1 (París) y desactiva la caché en las rutas /api/*.

Despliegue en Hetzner (o cualquier VPS Ubuntu/Debian)

# En el servidor, como root o con sudo
git clone tu-repo.git storefront && cd storefront
cp .env.example .env
nano .env                       # Rellena todas las variables
bash deploy/hetzner.sh

El script instala Docker si es necesario, construye la imagen, lanza el contenedor y expone el servicio en 127.0.0.1:3000. Añade Caddy o nginx como reverse-proxy para el TLS. Ejemplo de Caddyfile mínimo:

shop.ejemplo.com {
  encode zstd gzip
  reverse_proxy 127.0.0.1:3000
}

Endpoints REST expuestos

Todos los endpoints del plugin viven bajo el namespace dfhsk/v1. URL completa: https://ejemplo.com/wp-json/dfhsk/v1/…

Autenticación

  • POST /auth/login — body: { username, password } → devuelve { token, refresh_token, user }
  • POST /auth/refresh — body: { refresh_token } → devuelve un nuevo token
  • GET /auth/me — cabecera: Authorization: Bearer … → devuelve el usuario actual
  • POST /auth/register — body: { email, password, first_name, last_name }
  • POST /auth/logout — invalida el refresh token

Carrito

Cada llamada transmite el token de carrito mediante la cabecera X-DFHSK-Cart. El servidor devuelve un nuevo token en la misma cabecera en cada respuesta.

  • GET /cart — snapshot completo (items, totales, impuestos, envío)
  • POST /cart/add — body: { product_id, quantity, variation? }
  • POST /cart/update — body: { key, quantity }
  • POST /cart/remove — body: { key }
  • POST /cart/coupon — body: { code }
  • DELETE /cart/coupon/{code}
  • POST /cart/shipping — body: { country, postcode } → devuelve las tarifas aplicables
  • POST /cart/clear

Checkout

  • POST /checkout/create-order — body: { payment_method, billing, shipping? } → devuelve { order_id, order_key, redirect }. El redirect es la URL a la pasarela de pago (Stripe, PayPal, etc.).
  • GET /checkout/order/{id} — cabecera Authorization: Bearer … requerida

Configuración pública

  • GET /config — accesible sin autenticación. Devuelve { currency, base_country, countries, payment_methods, tax_settings }. El starter Next.js utiliza este endpoint para hidratar los formularios de checkout.

Webhooks ISR (lado Next.js)

El plugin envía peticiones POST a {FRONTEND_URL}/api/revalidate con la cabecera Authorization: Bearer {REVALIDATE_TOKEN}. El cuerpo es JSON:

{
  "paths": ["/products/chaqueta-lino", "/products"],
  "tags": ["product:chaqueta-lino"],
  "reason": "wc_update_product"
}

La ruta /api/revalidate entregada en el starter valida el token y luego llama a revalidatePath y revalidateTag para cada entrada.

Personalizar el starter

El código entregado está bajo licencia GPL v2 — puedes modificar, extender, redistribuir sin restricciones. Puntos de entrada habituales:

  • Paleta de colores: tailwind.config.ts, paleta brand (naranja por defecto)
  • Componentes tienda: src/components/shop/ (Header, Footer, ProductCard, CartProvider)
  • Páginas públicas: src/app/(shop)/
  • Páginas de cuenta: src/app/(auth)/
  • Formato de precios y fechas: src/lib/format.ts
  • Tipos TypeScript: src/types/woo.ts
  • Helper de llamadas API: src/lib/woo-rest.ts (funciones wooRest y dfhskFetch)

Para añadir una nueva página que liste por ejemplo los productos de una marca, duplica src/app/(shop)/products/page.tsx y adapta la consulta WooCommerce REST. La función wooRest<T>() gestiona la autenticación Basic automáticamente.

Resolución de problemas

Error CORS en la consola del navegador

El origen del front no está en la lista blanca. Añádelo en Ajustes → Orígenes CORS, uno por línea, sin barra final.

Los webhooks ISR responden 401

El REVALIDATE_TOKEN del lado Next.js no coincide con el token configurado del lado WordPress. Copia el valor exacto de los ajustes WP en el .env de Next.js, luego redespliega.

Login devuelve 403 pese a credenciales correctas

Verifica que la cuenta de usuario tiene una contraseña definida (no solo login social), que HTTPS está activo en producción, y que el secreto JWT tiene al menos 32 caracteres. Consulta la pestaña Diagnósticos.

El carrito se vacía entre dos páginas

En modo JWT, verifica que el starter lee y escribe correctamente el token en localStorage (clave dfhsk_cart_token). Abre el inspector del navegador → pestaña Application → Local Storage.

Un pedido creado en WooCommerce no aparece en Next.js

Verifica que el evento Pedidos está marcado en los eventos ISR y que el webhook se envía sin error (activa WP_DEBUG_LOG).

Ir más lejos

El starter es un punto de partida, no un producto terminado. Según tu proyecto, considera añadir:

  • Un motor de búsqueda instantáneo (Algolia, Meilisearch, Typesense) alimentado por los mismos webhooks ISR
  • Un CMS de contenido editorial del lado WordPress con el plugin ACF o similar, y una página Next.js dedicada
  • Una PWA con service worker para el modo sin conexión (ver también nuestro módulo dfpwa)
  • Personalización IA en tiempo real (ver dfsmartcontent)

Para cualquier duda técnica, contacta con el soporte de DataFirefly con tus logs y los resultados de la pestaña Diagnósticos.

¿Te ha resultado útil esta página?

¿Sigues atascado? Contacta con soporte