Build Theme Skill
Wählt basierend auf der natürlichsprachlichen Seitenbeschreibung des Benutzers ein Full Site Editing (FSE)-Block-Theme von WP.org aus, installiert und aktiviert es. Dieser Skill fragt die WP.org Themes API v1.2 nach FSE-Themes ab, bewertet die Ergebnisse mit Claudes kontextbezogenem Urteilsvermögen anhand des NL_PROMPT und installiert den besten Treffer. Eine kuratierte Fallback-Liste bietet eine garantierte Theme-Auswahl, wenn die API schlechte Ergebnisse liefert oder nicht verfügbar ist.
Kritische Reihenfolge: Dieser Skill läuft NACH build-mcp Abschnitt 2 (MCP-Adapter aktiviert, DB re-exportiert) und VOR build-content (das Seeding von Inhalten erfordert, dass das Theme für die Erkennung von Menü-Positionen aktiv ist).
Dieser Skill erwartet, dass die folgenden Variablen bereits vom aufrufenden Befehl gesetzt wurden:
BUILD_DIR— absoluter Pfad zum Build-Verzeichnis (gesetzt von build-scaffold Abschnitt 2)WP— das WP-CLI-Befehlspräfix (z. B.wp --path=$BUILD_DIRoder das Docker-Äquivalent, gesetzt von build-scaffold Abschnitt 4)NL_PROMPT— die natürlichsprachliche Beschreibung der Website des BenutzersSITE_TITLE— aus dem NL_PROMPT abgeleiteter Seitentitel (gesetzt vom aufrufenden Befehl vor diesem Skill)
Abschnitt 1: WP.org Themes API-Abfrage
Frage die WP.org Themes API v1.2 nach dem FSE-Block-Theme-Pool ab. Verwende den Tag full-site-editing zur Filterung – dies ist das kanonische öffentliche Signal für FSE-/Block-Themes. Kombiniere die Parameter search und tag NICHT: Die API ignoriert Tags, wenn search vorhanden ist. Claude bewertet die Theme-Relevanz kontextbezogen, nachdem der Pool abgerufen wurde.
echo "[Build] Frage WP.org Themes API nach FSE-Theme-Pool ab..."
# KRITISCHES ANTI-PATTERN: Verwende NICHT ?action=query_themes&request[search]=...&request[tag][]=full-site-editing
# Die API ignoriert tag[], wenn search vorhanden ist. Verwende eine reine Tag-Abfrage; Claude bewertet die Relevanz kontextbezogen.
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=$?
# Validiere die Antwort – überprüfe Exit-Code, nicht-leere Datei und JSON-Struktur
API_AVAILABLE=false
if [ $CURL_EXIT -eq 0 ] && [ -s "$FSE_THEMES_FILE" ]; then
# Zähle Themes in der Antwort – mindestens 3 erforderlich, damit Claude richtig bewerten kann
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] WP.org API hat $THEME_COUNT FSE-Themes zur Bewertung zurückgegeben."
else
echo "[Build] WP.org API hat weniger als 3 Themes zurückgegeben ($THEME_COUNT). Fallback auf kuratierte Liste."
fi
else
echo "[Build] WP.org API nicht verfügbar – verwende kuratierte Theme-Liste"
fi
Abschnitt 2: Theme-Bewertung und -Auswahl
Claude liest die API-JSON-Antwort und bewertet jedes Thema anhand des NL_PROMPT. Wenn die API einen brauchbaren Pool zurückgegeben hat, wählt Claude den besten Treffer basierend auf Relevanz, Popularität und Bewertung aus. Wenn die API fehlgeschlagen ist oder zu wenige Ergebnisse geliefert hat, wählt Claude basierend auf der Seitenkategorie im NL_PROMPT aus der kuratierten Fallback-Liste aus.
Bewertungskriterien (in priorisierter Reihenfolge):
- Relevanz von Name, Beschreibung und Tags für den im
NL_PROMPTbeschriebenen Seitentyp active_installs— beliebtheitssignal (höher = besser)rating— qualitätssignal (höher = besser)
Klassische Themes werden niemals ausgewählt, selbst wenn sie bei anderen Metriken besser abschneiden würden.
if [ "$API_AVAILABLE" = "true" ]; then
echo "[Build] Bewerte FSE-Themes anhand des NL-Prompts: \"$NL_PROMPT\""
echo "[Build] Lese Themes aus: $FSE_THEMES_FILE"
# Claude liest das FSE-Themes-JSON und bewertet jedes Theme:
# - themes[].name: Anzeigename
# - themes[].slug: WP.org-Installations-Slug
# - themes[].description: Theme-Beschreibung
# - themes[].tags: Theme-Funktions-/Kategorie-Tags
# - themes[].active_installs: Beliebtheit (Anzahl aktiver Installationen)
# - themes[].rating: Qualitätsbewertung (Skala 0-100)
#
# Claude wählt das Theme mit der besten Kombination aus:
# (1) Relevanz für den NL_PROMPT-Seitentyp
# (2) hohe active_installs
# (3) hohe Bewertung
#
# Verhalten bei keiner Übereinstimmung: Wenn kein Theme gut zum NL_PROMPT-Seitentyp passt,
# präsentiert Claude die Top-3-Kandidaten dem Benutzer und bittet um Auswahl.
# Dies unterbricht absichtlich den autonomen Ablauf – Zufriedenheit > Automatisierung.
#
# Nach der Auswahl setzt Claude:
THEME_SLUG="<von Claude aus den API-Ergebnissen ausgewählter Slug>"
THEME_NAME="<von Claude aus den API-Ergebnissen ausgewählter Anzeigename>"
else
# Kuratierte Fallback-Liste – ordnet Seitenkategorien bekannten FSE-kompatiblen Theme-Slugs zu
# Diese Themes sind verifizierte FSE-Block-Themes, die auf WP.org gepflegt werden.
# Aktualisiere diese Liste, wenn ein Theme von WP.org entfernt wird.
#
# Kategorie → Slug-Zuordnungen (Claude extrahiert die Seitenkategorie aus NL_PROMPT):
#
# portfolio / photography / creative → flavor
# business / corporate / agency → flavor
# blog / magazine / news → flavor
# restaurant / food / cafe → flavor
# ecommerce / shop / store → flavor
# default (jede andere) → twentytwentyfour
#
# twentytwentyfour ist der garantierte letzte Ausweg (gepflegt vom WordPress.org-Kernteam).
#
# Claude liest NL_PROMPT, bestimmt die Seitenkategorie und setzt:
THEME_SLUG="<von Claude aus der kuratierten Fallback-Liste ausgewählter Slug>"
THEME_NAME="<Anzeigename für das ausgewählte kuratierte Theme>"
fi
echo "[Build] Theme ausgewählt: $THEME_NAME ($THEME_SLUG)"
Abschnitt 3: Theme-Installation und -Aktivierung
Installiere und aktiviere das ausgewählte Theme mit WP-CLI. Wenn die Installation fehlschlägt, versuche Fallback-Kandidaten. Validiere immer die FSE-Kompatibilität, indem du nach der Installation nach theme.json suchst. Verwende Warnen-und-Fortfahren – breche den Build niemals aufgrund von Theme-Fehlern ab.
echo "[Build] Installiere Theme: $THEME_SLUG..."
install_theme() {
local slug="$1"
if $WP theme install "$slug" --activate 2>&1; then
echo "[Build] Theme installiert und aktiviert: $slug"
# FSE-Validierung – prüfe auf Vorhandensein von theme.json
# Claude hat aus dem FSE-Pool ausgewählt, dies ist also eine sekundäre Bestätigung.
# Falsch negative Ergebnisse sind möglich, wenn theme.json in einem Unterverzeichnis oder anders benannt ist.
if [ -f "$BUILD_DIR/wp-content/themes/$slug/theme.json" ]; then
echo "[Build] FSE validiert: theme.json gefunden."
else
echo "[Build] WARNUNG: theme.json nicht gefunden – Theme ist möglicherweise nicht FSE-kompatibel."
echo "[Build] Fahre fort – Claude hat dieses Theme aus dem full-site-editing-Tag-Pool ausgewählt."
fi
# Theme-Version abrufen
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] Theme installiert und aktiviert: $slug (v$THEME_VERSION)"
return 0
else
echo "[Build] WARNUNG: Theme-Installation fehlgeschlagen für Slug: $slug"
THEME_INSTALLED=false
return 1
fi
}
# Versuch 1: Installiere API-ausgewähltes oder kuratiertes Theme
if ! install_theme "$THEME_SLUG"; then
# Versuch 2: Wenn das API-ausgewählte Theme fehlschlug, versuche kuratierten Fallback
if [ "$API_AVAILABLE" = "true" ]; then
echo "[Build] Versuche kuratiertes Fallback-Theme für Seitenkategorie..."
# Claude bestimmt den kuratierten Fallback-Slug aus der NL_PROMPT-Seitenkategorie
# (siehe kuratierte Liste in Abschnitt 2) und wiederholt den Vorgang
FALLBACK_SLUG="twentytwentyfour" # Claude ersetzt dies ggf. durch den kategoriespezifischen Slug
if ! install_theme "$FALLBACK_SLUG"; then
# Versuch 3: Letzter Ausweg – twentytwentyfour (gepflegt von WordPress.org)
if [ "$FALLBACK_SLUG" != "twentytwentyfour" ]; then
echo "[Build] Versuche letzten Ausweg: twentytwentyfour..."
if ! install_theme "twentytwentyfour"; then
# Letzter Fallback – logge Warnung und fahre mit dem WP-Standard-Theme fort
echo "[Build] WARNUNG: Alle Theme-Installationsversuche fehlgeschlagen."
echo "[Build] WARNUNG: Build wird mit dem WordPress-Standard-Theme fortgesetzt."
THEME_SLUG="default"
THEME_NAME="WordPress Standard"
THEME_VERSION="unknown"
THEME_INSTALLED=false
fi
else
# twentytwentyfour ist bereits fehlgeschlagen – fahre mit Standard fort
echo "[Build] WARNUNG: Alle Theme-Installationsversuche fehlgeschlagen."
echo "[Build] WARNUNG: Build wird mit dem WordPress-Standard-Theme fortgesetzt."
THEME_SLUG="default"
THEME_NAME="WordPress Standard"
THEME_VERSION="unknown"
THEME_INSTALLED=false
fi
fi
else
# Kuratiertes Theme fehlgeschlagen – versuche twentytwentyfour als letzten Ausweg
if [ "$THEME_SLUG" != "twentytwentyfour" ]; then
echo "[Build] Versuche letzten Ausweg: twentytwentyfour..."
if ! install_theme "twentytwentyfour"; then
echo "[Build] WARNUNG: Alle Theme-Installationsversuche fehlgeschlagen."
echo "[Build] WARNUNG: Build wird mit dem WordPress-Standard-Theme fortgesetzt."
THEME_SLUG="default"
THEME_NAME="WordPress Standard"
THEME_VERSION="unknown"
THEME_INSTALLED=false
fi
else
echo "[Build] WARNUNG: Alle Theme-Installationsversuche fehlgeschlagen."
echo "[Build] WARNUNG: Build wird mit dem WordPress-Standard-Theme fortgesetzt."
THEME_SLUG="default"
THEME_NAME="WordPress Standard"
THEME_VERSION="unknown"
THEME_INSTALLED=false
fi
fi
fi
# Lösche temporäre API-Antwortdatei
rm -f "$FSE_THEMES_FILE"
Abschnitt 4: Seitentitel aktualisieren
Aktualisiere den WordPress-Seitentitel und die Seitenbeschreibung (Tagline), um der im NL_PROMPT beschriebenen Website zu entsprechen. Der Seitentitel wurde bereits während der build-scaffold-WP-Installation gesetzt (--title="$SITE_TITLE"), aber dieser Schritt ermöglicht es, die Tagline mit einer kontextuellen Beschreibung aus dem NL-Prompt zu setzen.
echo "[Build] Setze Seitentitel und Tagline..."
# Seitentitel aktualisieren (stimmt möglicherweise bereits mit build-scaffold --title überein, aber zur Bestätigung aktualisieren)
$WP option update blogname "$SITE_TITLE" 2>&1
# Claude generiert eine kurze Tagline (eine Zeile, keine Anführungszeichen) aus dem NL_PROMPT
# Beispiele:
# NL_PROMPT: "a portfolio site for a freelance photographer"
# → Tagline: "Momente festhalten, die zählen"
#
# NL_PROMPT: "a restaurant website for an Italian bistro in Sydney"
# → Tagline: "Authentische italienische Aromen im Herzen von Sydney"
#
# Claude setzt SITE_TAGLINE auf die generierte Tagline, dann:
SITE_TAGLINE="<von Claude aus NL_PROMPT generierte Tagline>"
$WP option update blogdescription "$SITE_TAGLINE" 2>&1
echo "[Build] Seitentitel gesetzt: $SITE_TITLE"
echo "[Build] Seiten-Tagline gesetzt: $SITE_TAGLINE"
Implementierungshinweise
Pipeline-Position: Dieser Skill läuft in der NL-Build-Pipeline strikt NACH build-mcp Abschnitt 2 (MCP-Adapter aktiviert, Datenbank re-exportiert) und VOR build-content. Das Theme muss vor dem Seeding von Inhalten aktiv sein, da build-content $WP menu location list verwendet, um die Navigationspositionen des aktiven Themes zu ermitteln – dies erfordert, dass das Ziel-Theme bereits installiert und aktiv ist.
Docker-MySQL-Container: Der ephemere Docker-MySQL-Container aus build-scaffold Abschnitt 3 muss noch laufen, wenn dieser Skill ausgeführt wird. Die WP-CLI-Theme-Installation schreibt in die WordPress-Options-Tabelle (Slug des aktiven Themes). Der in build-scaffold Abschnitt 3 gesetzte EXIT-Trap bleibt für die gesamte Build-Sitzung aktiv und feuert nur, wenn der vollständige Befehl beendet wird – nicht zwischen Skill-Aufrufen.
Ausgabevariablen: Die folgenden Variablen werden von diesem Skill gesetzt und von nachgelagerten Skills (build-content, build-setup) konsumiert:
THEME_SLUG— Slug des installierten Themes (z. B.twentytwentyfour,flavor)THEME_NAME— Anzeigename (z. B.Twenty Twenty-Four,Flavor)THEME_VERSION— Installierte Versionszeichenfolge (z. B.1.3,unknownfalls nicht erkennbar)THEME_INSTALLED—true, wenn die Installation erfolgreich war,false, wenn alle Fallbacks fehlgeschlagen sind
Wartung der kuratierten Fallback-Liste: Die kuratierte Liste ordnet Seitenkategorien bekannten FSE-Block-Themes auf WP.org zu. Wenn ein Slug eines kuratierten Themes von WP.org entfernt wird (sodass wp theme install mit "not found" fehlschlägt), aktualisiere diese Liste mit einem aktuellen FSE-kompatiblen Ersatz. twentytwentyfour ist der garantierte letzte Ausweg – es wird vom WordPress.org-Kernteam gepflegt und wird nicht entfernt.
Keine Anpassungen nach der Installation (festgelegte Entscheidung): Gemäß der in CONTEXT.md dokumentierten Benutzerentscheidung werden keine theme.json-Überschreibungen, Child-Themes oder Global-Styles-Änderungen nach der Installation vorgenommen. Das Theme wird so installiert und aktiviert, wie es von WP.org kommt. Sein integriertes Design bleibt unverändert.
Zuverlässigkeit der FSE-Validierung: Die theme.json-Prüfung ist eine sekundäre Bestätigung – Claude hat die Themes bereits anhand des full-site-editing-Tags in der API-Abfrage gefiltert. Eine Meldung "WARNUNG: theme.json nicht gefunden" weist nicht auf einen Fehler hin: Das Theme speichert theme.json möglicherweise an einem nicht standardmäßigen Ort, oder der WP.org-Tag wurde korrekt gesetzt, aber die Dateipfad-Prüfung ist fehlgeschlagen. Der Build wird unabhängig davon fortgesetzt.
Referenzen:
- @references/wp-block-themes/SKILL.md — FSE-Theme-Struktur, theme.json-Schema, Blockvorlagenmuster
- @references/wp-wpcli-and-ops/SKILL.md — WP-CLI-Theme-Befehlsreferenz, --activate-Flag, --field-Ausgabe