Habilidad de Construcción de Tema
Selecciona, instala y activa un tema de bloques de Edición Completa del Sitio (FSE) desde WP.org basado en la descripción del sitio del usuario en lenguaje natural. Esta habilidad consulta la API de Temas de WP.org v1.2 para temas FSE, evalúa los resultados según la solicitud en lenguaje natural (NL_PROMPT) utilizando el juicio contextual de Claude, e instala la mejor coincidencia. Una lista curada de respaldo proporciona una selección de tema garantizada cuando la API devuelve resultados deficientes o no está disponible.
Secuenciación crítica: Esta habilidad se ejecuta DESPUÉS de la build-mcp Sección 2 (adaptador MCP activado, base de datos reexportada) y ANTES de build-content (el sembrado de contenido requiere que el tema esté activo para el descubrimiento de ubicaciones de menú).
Esta habilidad espera que las siguientes variables ya estén definidas por el comando que la invoca:
BUILD_DIR— ruta absoluta al directorio de construcción (definida porbuild-scaffoldSección 2)WP— el prefijo del comando WP-CLI (p. ej.,wp --path=$BUILD_DIRo el equivalente en Docker, definido porbuild-scaffoldSección 4)NL_PROMPT— la cadena de descripción del sitio en lenguaje natural del usuarioSITE_TITLE— título del sitio derivado deNL_PROMPT(definido por el comando que invoca antes de esta habilidad)
Sección 1: Consulta a la API de Temas de WP.org
Consulta la API de Temas de WP.org v1.2 para obtener el conjunto de temas de bloques FSE. Usa la etiqueta full-site-editing para filtrar: esta es la señal pública canónica para temas FSE/de bloques. NO combines los parámetros search y tag: la API ignora las etiquetas cuando search está presente. Claude evalúa la relevancia del tema en contexto después de obtener el conjunto.
echo "[Build] Consultando la API de Temas de WP.org para el conjunto de temas FSE..."
# PATRÓN ANTIPATRÓN CRÍTICO: NO usar ?action=query_themes&request[search]=...&request[tag][]=full-site-editing
# La API ignora tag[] cuando search está presente. Usar solo consulta por etiqueta; Claude evalúa la relevancia en contexto.
FSE_THEMES_FILE="/tmp/fse_themes_$$.json"
curl -s --max-time 10 \
"https://api.wordpress.org/themes/info/1.2/?action=query_themes&request[tag][]=full-site-editing&request[browse]=popular&request[per_page]=50&request[fields][active_installs]=true&request[fields][rating]=true&request[fields][description]=true&request[fields][tags]=true" \
-o "$FSE_THEMES_FILE"
CURL_EXIT=$?
# Validar respuesta — verificar código de salida, archivo no vacío y estructura JSON
API_AVAILABLE=false
if [ $CURL_EXIT -eq 0 ] && [ -s "$FSE_THEMES_FILE" ]; then
# Contar temas en la respuesta — se necesitan al menos 3 para que Claude evalúe correctamente
THEME_COUNT=$(python3 -c "import json,sys; d=json.load(open(sys.argv[1])); print(len(d.get('themes', [])))" "$FSE_THEMES_FILE" 2>/dev/null || echo "0")
if [ "$THEME_COUNT" -ge 3 ]; then
API_AVAILABLE=true
echo "[Build] La API de WP.org devolvió $THEME_COUNT temas FSE para evaluación."
else
echo "[Build] La API de WP.org devolvió menos de 3 temas ($THEME_COUNT). Usando lista curada."
fi
else
echo "[Build] API de WP.org no disponible — usando lista curada de temas"
fi
Sección 2: Evaluación y Selección del Tema
Claude lee la respuesta JSON de la API y evalúa cada tema según NL_PROMPT. Si la API devolvió un conjunto viable, Claude selecciona la mejor coincidencia usando relevancia, popularidad y valoración. Si la API falló o devolvió muy pocos resultados, Claude selecciona de la lista curada de respaldo según la categoría del sitio en NL_PROMPT.
Criterios de puntuación (en orden de prioridad):
- Relevancia del nombre, descripción y etiquetas para el tipo de sitio descrito en
NL_PROMPT active_installs— señal de popularidad (más alto = mejor)rating— señal de calidad (más alto = mejor)
Los temas clásicos nunca se seleccionan, incluso si puntuaran más alto en otras métricas.
if [ "$API_AVAILABLE" = "true" ]; then
echo "[Build] Evaluando temas FSE según solicitud NL: \"$NL_PROMPT\""
echo "[Build] Leyendo temas desde: $FSE_THEMES_FILE"
# Claude lee el JSON de temas FSE y evalúa cada tema:
# - themes[].name: nombre para mostrar
# - themes[].slug: slug de instalación en WP.org
# - themes[].description: descripción del tema
# - themes[].tags: etiquetas de características/categorías del tema
# - themes[].active_installs: popularidad (número de instalaciones activas)
# - themes[].rating: valoración de calidad (escala 0-100)
#
# Claude selecciona el tema con la mejor combinación de:
# (1) relevancia para el tipo de sitio de NL_PROMPT
# (2) active_installs alta
# (3) rating alta
#
# Comportamiento sin coincidencia: Si ningún tema puntúa bien para el tipo de sitio de NL_PROMPT,
# Claude presenta los 3 mejores candidatos al usuario y le pide que elija.
# Esto rompe el flujo autónomo intencionalmente — satisfacción > automatización.
#
# Después de la selección, Claude establece:
THEME_SLUG="<slug seleccionado por Claude de los resultados de la API>"
THEME_NAME="<nombre para mostrar seleccionado por Claude de los resultados de la API>"
else
# Lista curada de respaldo — asigna categorías de sitio a slugs de temas FSE conocidos
# Estos temas son temas de bloques FSE verificados y mantenidos en WP.org.
# Actualiza esta lista si un tema se elimina de WP.org.
#
# Categoría → Asignaciones de Slug (Claude extrae la categoría del sitio de NL_PROMPT):
#
# portafolio / fotografía / creativo → flavor
# negocio / corporativo / agencia → flavor
# blog / revista / noticias → flavor
# restaurante / comida / cafetería → flavor
# comercio electrónico / tienda / almacén → flavor
# predeterminado (cualquier otro) → twentytwentyfour
#
# twentytwentyfour es el respaldo de último recurso garantizado (mantenido por el equipo central de WordPress.org).
#
# Claude lee NL_PROMPT, determina la categoría del sitio y establece:
THEME_SLUG="<slug seleccionado por Claude de la lista curada de respaldo>"
THEME_NAME="<nombre para mostrar del tema curado seleccionado>"
fi
echo "[Build] Tema seleccionado: $THEME_NAME ($THEME_SLUG)"
Sección 3: Instalación y Activación del Tema
Instala y activa el tema seleccionado usando WP-CLI. Si la instalación falla, intenta con candidatos de respaldo. Siempre valida la compatibilidad FSE verificando la presencia de theme.json después de la instalación. Usa advertencia-y-continuar — nunca abortes la construcción por fallos del tema.
echo "[Build] Instalando tema: $THEME_SLUG..."
install_theme() {
local slug="$1"
if $WP theme install "$slug" --activate 2>&1; then
echo "[Build] Tema instalado y activado: $slug"
# Validación FSE — verificar presencia de theme.json
# Claude seleccionó del conjunto FSE, por lo que esto es una confirmación secundaria.
# Es posible un falso negativo si theme.json está en un subdirectorio o se nombra de forma diferente.
if [ -f "$BUILD_DIR/wp-content/themes/$slug/theme.json" ]; then
echo "[Build] FSE validado: theme.json encontrado."
else
echo "[Build] ADVERTENCIA: theme.json no encontrado — el tema podría no ser compatible con FSE."
echo "[Build] Continuando — Claude seleccionó este tema del conjunto de la etiqueta full-site-editing."
fi
# Obtener versión del tema
THEME_VERSION=$($WP theme get "$slug" --field=version 2>/dev/null || \
grep -m 1 "^Version:" "$BUILD_DIR/wp-content/themes/$slug/style.css" 2>/dev/null | \
sed 's/Version: //' | tr -d '[:space:]' || \
echo "unknown")
THEME_INSTALLED=true
echo "[Build] Tema instalado y activado: $slug (v$THEME_VERSION)"
return 0
else
echo "[Build] ADVERTENCIA: Falló la instalación del tema para el slug: $slug"
THEME_INSTALLED=false
return 1
fi
}
# Intento 1: Instalar tema seleccionado por API o curado
if ! install_theme "$THEME_SLUG"; then
# Intento 2: Si falló el tema seleccionado por API, probar respaldo curado
if [ "$API_AVAILABLE" = "true" ]; then
echo "[Build] Probando tema curado de respaldo para la categoría del sitio..."
# Claude determina el slug de respaldo curado de la categoría del sitio NL_PROMPT
# (ver lista curada de la Sección 2) y reintenta
FALLBACK_SLUG="twentytwentyfour" # Claude reemplaza esto con un slug específico de categoría si corresponde
if ! install_theme "$FALLBACK_SLUG"; then
# Intento 3: Último recurso — twentytwentyfour (mantenido por WordPress.org)
if [ "$FALLBACK_SLUG" != "twentytwentyfour" ]; then
echo "[Build] Probando respaldo de último recurso: twentytwentyfour..."
if ! install_theme "twentytwentyfour"; then
# Respaldo final — registrar advertencia y continuar con el tema predeterminado de WP
echo "[Build] ADVERTENCIA: Todos los intentos de instalación del tema fallaron."
echo "[Build] ADVERTENCIA: La construcción continúa con el tema predeterminado de WordPress."
THEME_SLUG="default"
THEME_NAME="WordPress Default"
THEME_VERSION="unknown"
THEME_INSTALLED=false
fi
else
# twentytwentyfour ya falló — continuar con el predeterminado
echo "[Build] ADVERTENCIA: Todos los intentos de instalación del tema fallaron."
echo "[Build] ADVERTENCIA: La construcción continúa con el tema predeterminado de WordPress."
THEME_SLUG="default"
THEME_NAME="WordPress Default"
THEME_VERSION="unknown"
THEME_INSTALLED=false
fi
fi
else
# El tema curado falló — probar twentytwentyfour como último recurso
if [ "$THEME_SLUG" != "twentytwentyfour" ]; then
echo "[Build] Probando respaldo de último recurso: twentytwentyfour..."
if ! install_theme "twentytwentyfour"; then
echo "[Build] ADVERTENCIA: Todos los intentos de instalación del tema fallaron."
echo "[Build] ADVERTENCIA: La construcción continúa con el tema predeterminado de WordPress."
THEME_SLUG="default"
THEME_NAME="WordPress Default"
THEME_VERSION="unknown"
THEME_INSTALLED=false
fi
else
echo "[Build] ADVERTENCIA: Todos los intentos de instalación del tema fallaron."
echo "[Build] ADVERTENCIA: La construcción continúa con el tema predeterminado de WordPress."
THEME_SLUG="default"
THEME_NAME="WordPress Default"
THEME_VERSION="unknown"
THEME_INSTALLED=false
fi
fi
fi
# Limpiar archivo de respuesta temporal de la API
rm -f "$FSE_THEMES_FILE"
Sección 4: Actualización del Título del Sitio
Actualiza el título y el lema del sitio de WordPress para que coincidan con el sitio descrito en NL_PROMPT. El título del sitio ya se estableció durante la instalación de WP de build-scaffold (--title="$SITE_TITLE"), pero este paso permite establecer el lema con una descripción contextual generada a partir de la solicitud en lenguaje natural.
echo "[Build] Estableciendo título y lema del sitio..."
# Actualizar título del sitio (puede que ya coincida con --title de build-scaffold, pero se actualiza para confirmar)
$WP option update blogname "$SITE_TITLE" 2>&1
# Claude genera un lema breve (una línea, sin comillas) a partir de NL_PROMPT
# Ejemplos:
# NL_PROMPT: "un sitio portafolio para un fotógrafo freelance"
# → Lema: "Capturando momentos que importan"
#
# NL_PROMPT: "un sitio web de restaurante para una trattoria italiana en Madrid"
# → Lema: "Sabores italianos auténticos en el corazón de Madrid"
#
# Claude establece SITE_TAGLINE con el lema generado, luego:
SITE_TAGLINE="<lema generado por Claude a partir de NL_PROMPT>"
$WP option update blogdescription "$SITE_TAGLINE" 2>&1
echo "[Build] Título del sitio establecido: $SITE_TITLE"
echo "[Build] Lema del sitio establecido: $SITE_TAGLINE"
Notas de Implementación
Posición en el pipeline: Esta habilidad se ejecuta en el pipeline de construcción NL estrictamente DESPUÉS de build-mcp Sección 2 (adaptador MCP activado, base de datos reexportada) y ANTES de build-content. El tema debe estar activo antes del sembrado de contenido porque build-content usa $WP menu location list para descubrir las ubicaciones de navegación del tema activo—esto requiere que el tema objetivo ya esté instalado y activo.
Contenedor Docker MySQL: El contenedor Docker MySQL efímero de build-scaffold Sección 3 debe seguir en ejecución cuando se ejecuta esta habilidad. La instalación del tema con WP-CLI escribe en la tabla de opciones de WordPress (slug del tema activo). El trap EXIT establecido en build-scaffold Sección 3 permanece activo durante toda la sesión de construcción y se dispara solo cuando el comando completo finaliza—no entre invocaciones de habilidades.
Variables de salida: Las siguientes variables son establecidas por esta habilidad y consumidas por habilidades posteriores (build-content, build-setup):
THEME_SLUG— slug del tema instalado (p. ej.,twentytwentyfour,flavor)THEME_NAME— nombre para mostrar (p. ej.,Twenty Twenty-Four,Flavor)THEME_VERSION— cadena de versión instalada (p. ej.,1.3,unknownsi no se puede detectar)THEME_INSTALLED—truesi la instalación tuvo éxito,falsesi todos los respaldos fallaron
Mantenimiento de la lista curada de respaldo: La lista curada asigna categorías de sitio a temas de bloques FSE conocidos en WP.org. Si un tema curado se elimina de WP.org (causando que wp theme install falle con "no encontrado"), actualiza esta lista con un reemplazo compatible con FSE actual. twentytwentyfour es el respaldo de último recurso garantizado—es mantenido por el equipo central de WordPress.org y no será eliminado.
Sin personalización posterior a la instalación (decisión bloqueada): Según la decisión del usuario registrada en CONTEXT.md, no se aplican anulaciones de theme.json, temas hijo ni modificaciones de Estilos Globales después de la instalación. El tema se instala y activa tal cual desde WP.org. Su diseño incorporado se entrega sin cambios.
Fiabilidad de la validación FSE: La comprobación de theme.json es una confirmación secundaria—Claude ya filtró los temas por la etiqueta full-site-editing en la consulta de la API. Un mensaje "ADVERTENCIA: theme.json no encontrado" no indica un error: el tema puede almacenar theme.json en una ubicación no estándar, o la etiqueta de WP.org puede haberse establecido correctamente pero falló la verificación de la ruta del archivo. La construcción continúa independientemente.
Referencias:
- @references/wp-block-themes/SKILL.md — estructura de temas FSE, esquema de theme.json, patrones de plantillas de bloques
- @references/wp-wpcli-and-ops/SKILL.md — referencia del comando de tema de WP-CLI, indicador --activate, salida --field