建置佈景主題技能
根據使用者的自然語言網站描述,從 WP.org 選擇、安裝並啟用一個全站編輯 (FSE) 區塊佈景主題。此技能會查詢 WP.org Themes API v1.2 以取得 FSE 佈景主題,利用 Claude 的上下文判斷力來評估結果與自然語言提示 (NL prompt) 的相關性,然後安裝最佳匹配。當 API 回傳結果不佳或無法使用時,會提供一個經人工整理的備選清單,以確保能選出佈景主題。
關鍵執行順序: 此技能必須在 build-mcp 的第二節(MCP 適配器已啟動,資料庫已重新匯出)之後,以及在 build-content(內容植入需要佈景主題啟用才能發現選單位置)之前執行。
此技能預期呼叫它的命令已設定好以下變數:
BUILD_DIR— 建置目錄的絕對路徑(由build-scaffold第二節設定)WP— WP-CLI 命令前綴(例如wp --path=$BUILD_DIR或 Docker 等效命令,由build-scaffold第四節設定)NL_PROMPT— 使用者的自然語言網站描述字串SITE_TITLE— 從自然語言提示中衍生的網站標題(由呼叫此技能前的命令設定)
第一節:WP.org Themes API 查詢
查詢 WP.org Themes API v1.2 以取得 FSE 區塊佈景主題池。使用 full-site-editing 標籤進行篩選 — 這是 FSE/區塊佈景主題的權威公開訊號。請勿同時使用 search 和 tag 參數:當 search 存在時,API 會忽略標籤。Claude 在取得佈景主題池後,會於上下文中評估其相關性。
echo "[建置] 正在向 WP.org Themes API 查詢 FSE 佈景主題池..."
# 關鍵反模式:請勿使用 ?action=query_themes&request[search]=...&request[tag][]=full-site-editing
# 當 search 存在時,API 會忽略 tag[]。請僅使用標籤查詢;Claude 會於上下文中評估相關性。
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=$?
# 驗證回應 — 檢查退出碼、檔案非空和 JSON 結構
API_AVAILABLE=false
if [ $CURL_EXIT -eq 0 ] && [ -s "$FSE_THEMES_FILE" ]; then
# 計算回應中的佈景主題數量 — 為了讓 Claude 正確評估,至少需要 3 個
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 "[建置] WP.org API 傳回了 $THEME_COUNT 個 FSE 佈景主題以供評估。"
else
echo "[建置] WP.org API 傳回的佈景主題少於 3 個 ($THEME_COUNT)。將使用備選清單。"
fi
else
echo "[建置] WP.org API 無法使用 — 將使用經整理的備選佈景主題清單"
fi
第二節:佈景主題評估與選擇
Claude 讀取 API JSON 回應,並根據 NL_PROMPT 評估每個佈景主題。如果 API 傳回了可行的佈景主題池,Claude 會使用相關性、熱門度和評分來選擇最佳匹配。如果 API 失敗或傳回結果太少,Claude 會根據 NL_PROMPT 中的網站類別從備選清單中選擇。
評分標準(按優先順序排列):
- 佈景主題名稱、描述和標籤與
NL_PROMPT所述網站類型的相關性 active_installs— 熱門度訊號(越高越好)rating— 品質訊號(越高越好)
絕不選擇傳統佈景主題,即使它們在其他指標上得分更高。
if [ "$API_AVAILABLE" = "true" ]; then
echo "[建置] 正在根據 NL 提示評估 FSE 佈景主題:\"$NL_PROMPT\""
echo "[建置] 正在從以下檔案讀取佈景主題:$FSE_THEMES_FILE"
# Claude 讀取 FSE 佈景主題 JSON 並評估每個主題:
# - themes[].name: 顯示名稱
# - themes[].slug: WP.org 安裝 slug
# - themes[].description: 佈景主題描述
# - themes[].tags: 佈景主題功能/類別標籤
# - themes[].active_installs: 熱門度(活躍安裝數)
# - themes[].rating: 品質評分(0-100 分)
#
# Claude 選擇具有以下最佳組合的佈景主題:
# (1) 與 NL_PROMPT 網站類型的相關性
# (2) 高 active_installs
# (3) 高 rating
#
# 無匹配行為:如果沒有佈景主題能針對 NL_PROMPT 網站類型獲得高分,
# Claude 會向使用者顯示前 3 個候選者,並請他們選擇。
# 這會故意中斷自動流程 — 使用者滿意度比自動化更重要。
#
# 選擇完成後,Claude 會設定:
THEME_SLUG="<Claude 從 API 結果中選擇的 slug>"
THEME_NAME="<Claude 從 API 結果中選擇的顯示名稱>"
else
# 經整理的備選清單 — 將網站類別對應到已知的 FSE 相容佈景主題 slug
# 這些是在 WP.org 上維護、經過驗證的 FSE 區塊佈景主題。
# 如果某個佈景主題從 WP.org 上移除,請更新此清單。
#
# 類別 → Slug 對應(Claude 從 NL_PROMPT 中提取網站類別):
#
# portfolio / photography / creative → flavor
# business / corporate / agency → flavor
# blog / magazine / news → flavor
# restaurant / food / cafe → flavor
# ecommerce / shop / store → flavor
# default (任何其他) → twentytwentyfour
#
# twentytwentyfour 是保證的最終備選方案(由 WordPress.org 核心團隊維護)。
#
# Claude 讀取 NL_PROMPT,確定網站類別,然後設定:
THEME_SLUG="<Claude 從備選清單中選擇的 slug>"
THEME_NAME="<所選備選佈景主題的顯示名稱>"
fi
echo "[建置] 已選擇佈景主題:$THEME_NAME ($THEME_SLUG)"
第三節:佈景主題安裝與啟用
使用 WP-CLI 安裝並啟用所選的佈景主題。如果安裝失敗,請嘗試備選候選者。安裝後務必透過檢查 theme.json 來驗證 FSE 相容性。採取「警告並繼續」策略 — 絕不因佈景主題失敗而中止建置。
echo "[建置] 正在安裝佈景主題:$THEME_SLUG..."
install_theme() {
local slug="$1"
if $WP theme install "$slug" --activate 2>&1; then
echo "[建置] 佈景主題已安裝並啟用:$slug"
# FSE 驗證 — 檢查 theme.json 是否存在
# Claude 已經從 FSE 池中選擇,所以這是次要確認。
# 如果 theme.json 位於子目錄或名稱不同,可能會產生偽陰性。
if [ -f "$BUILD_DIR/wp-content/themes/$slug/theme.json" ]; then
echo "[建置] FSE 驗證通過:已找到 theme.json。"
else
echo "[建置] 警告:找不到 theme.json — 此佈景主題可能不相容於 FSE。"
echo "[建置] 繼續執行 — Claude 已從 full-site-editing 標籤池中選擇了此佈景主題。"
fi
# 取得佈景主題版本
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 "[建置] 佈景主題已安裝並啟用:$slug (v$THEME_VERSION)"
return 0
else
echo "[建置] 警告:安裝 slug 為 $slug 的佈景主題失敗"
THEME_INSTALLED=false
return 1
fi
}
# 嘗試 1:安裝 API 選擇的或備選佈景主題
if ! install_theme "$THEME_SLUG"; then
# 嘗試 2:如果 API 選擇的佈景主題失敗,嘗試使用備選清單
if [ "$API_AVAILABLE" = "true" ]; then
echo "[建置] 正在嘗試使用網站類別的備選佈景主題..."
# Claude 根據 NL_PROMPT 網站類別決定備選 slug(詳見第二節備選清單)並重試
FALLBACK_SLUG="twentytwentyfour" # 如果適用,Claude 會將其替換為特定類別的 slug
if ! install_theme "$FALLBACK_SLUG"; then
# 嘗試 3:最終方案 — twentytwentyfour(由 WordPress.org 維護)
if [ "$FALLBACK_SLUG" != "twentytwentyfour" ]; then
echo "[建置] 正在嘗試最終備案:twentytwentyfour..."
if ! install_theme "twentytwentyfour"; then
# 最終備案 — 記錄警告並使用 WP 預設佈景主題繼續
echo "[建置] 警告:所有佈景主題安裝嘗試均失敗。"
echo "[建置] 警告:建置將使用 WordPress 預設佈景主題繼續。"
THEME_SLUG="default"
THEME_NAME="WordPress 預設"
THEME_VERSION="unknown"
THEME_INSTALLED=false
fi
else
# twentytwentyfour 已經失敗 — 使用預設佈景主題繼續
echo "[建置] 警告:所有佈景主題安裝嘗試均失敗。"
echo "[建置] 警告:建置將使用 WordPress 預設佈景主題繼續。"
THEME_SLUG="default"
THEME_NAME="WordPress 預設"
THEME_VERSION="unknown"
THEME_INSTALLED=false
fi
fi
else
# 備選佈景主題失敗 — 嘗試 twentytwentyfour 作為最終方案
if [ "$THEME_SLUG" != "twentytwentyfour" ]; then
echo "[建置] 正在嘗試最終備案:twentytwentyfour..."
if ! install_theme "twentytwentyfour"; then
echo "[建置] 警告:所有佈景主題安裝嘗試均失敗。"
echo "[建置] 警告:建置將使用 WordPress 預設佈景主題繼續。"
THEME_SLUG="default"
THEME_NAME="WordPress 預設"
THEME_VERSION="unknown"
THEME_INSTALLED=false
fi
else
echo "[建置] 警告:所有佈景主題安裝嘗試均失敗。"
echo "[建置] 警告:建置將使用 WordPress 預設佈景主題繼續。"
THEME_SLUG="default"
THEME_NAME="WordPress 預設"
THEME_VERSION="unknown"
THEME_INSTALLED=false
fi
fi
fi
# 清理暫存的 API 回應檔案
rm -f "$FSE_THEMES_FILE"
第四節:更新網站標題
更新 WordPress 網站標題和標語,使其符合 NL_PROMPT 中所描述的網站。網站標題已在 build-scaffold WordPress 安裝時設定(--title="$SITE_TITLE"),但此步驟允許根據 NL 提示產生的上下文描述來設定標語。
echo "[建置] 正在設定網站標題與標語..."
# 更新網站標題(可能與 build-scaffold --title 設定的相同,但再次確認)
$WP option update blogname "$SITE_TITLE" 2>&1
# Claude 從 NL_PROMPT 中產生一個簡短的標語(一行,不含引號)
# 範例:
# NL_PROMPT: "一個自由接案攝影師的作品集網站"
# → 標語:"捕捉重要時刻"
#
# NL_PROMPT: "一個位於雪梨的義式小餐館網站"
# → 標語:"在雪梨市中心品嚐道地義式風味"
#
# Claude 將 SITE_TAGLINE 設定為產生的標語,然後:
SITE_TAGLINE="<Claude 從 NL_PROMPT 產生的標語>"
$WP option update blogdescription "$SITE_TAGLINE" 2>&1
echo "[建置] 網站標題已設定:$SITE_TITLE"
echo "[建置] 網站標語已設定:$SITE_TAGLINE"
實作注意事項
管線位置: 此技能在 NL 建置管線中,嚴格在 build-mcp 第二節(MCP 適配器已啟動,資料庫已重新匯出)之後,以及在 build-content 之前執行。佈景主題必須在內容植入前處於啟用狀態,因為 build-content 會使用 $WP menu location list 來發現啟用中佈景主題的導覽選單位置 — 這要求目標佈景主題必須已經安裝並啟用。
Docker MySQL 容器: 來自 build-scaffold 第三節的暫存 Docker MySQL 容器在此技能執行時必須仍在運行。WP-CLI 佈景主題安裝會寫入 WordPress 選項表(啟用中佈景主題 slug)。在 build-scaffold 第三節設定的 EXIT 陷阱在整個建置階段中保持有效,並僅在完整命令退出時觸發 — 不會在技能調用之間觸發。
輸出變數: 此技能會設定下列變數,供下游技能(build-content、build-setup)使用:
THEME_SLUG— 已安裝的佈景主題 slug(例如twentytwentyfour、flavor)THEME_NAME— 顯示名稱(例如Twenty Twenty-Four、Flavor)THEME_VERSION— 已安裝的版本字串(例如1.3,若無法偵測則為unknown)THEME_INSTALLED— 若安裝成功則為true,若所有備案均失敗則為false
備選清單維護: 備選清單將網站類別對應到 WP.org 上已知的 FSE 區塊佈景主題。如果某個備選佈景主題的 slug 從 WP.org 上移除(導致 wp theme install 失敗並顯示「not found」),請使用目前的 FSE 相容替代品更新此清單。twentytwentyfour 是保證的最終備案 — 它由 WordPress.org 核心團隊維護,不會被移除。
不安裝後自訂(鎖定決策): 根據 CONTEXT.md 中記錄的使用者決策,安裝後不應用任何 theme.json 覆蓋、子佈景主題或全域樣式修改。佈景主題將按原樣從 WP.org 安裝並啟用。其內建設計將按原樣提供。
FSE 驗證可靠性: 檢查 theme.json 是次要確認 — Claude 已在 API 查詢中透過 full-site-editing 標籤篩選了佈景主題。出現「警告:找不到 theme.json」的訊息並不表示錯誤:該佈景主題可能將 theme.json 存放在非標準位置,或者 WP.org 標籤設定正確但檔案路徑檢查失敗。建置無論如何都會繼續。
參考資料:
- @references/wp-block-themes/SKILL.md — FSE 佈景主題結構、theme.json 架構、區塊範本模式
- @references/wp-wpcli-and-ops/SKILL.md — WP-CLI 佈景主題命令參考、--activate 標誌、--field 輸出