테마 빌드 스킬
사용자의 자연어 사이트 설명을 기반으로 WP.org에서 FSE(전체 사이트 편집) 블록 테마를 선택, 설치, 활성화합니다. 이 스킬은 WP.org Themes API v1.2를 쿼리하여 FSE 테마를 가져오고, Claude의 문맥 내 판단을 사용하여 NL 프롬프트에 대해 결과를 평가한 후 최적의 일치 테마를 설치합니다. API 결과가 좋지 않거나 사용할 수 없는 경우 큐레이트된 대체 목록이 보장된 테마 선택을 제공합니다.
중요한 실행 순서: 이 스킬은 build-mcp 섹션 2(MCP 어댑터 활성화, DB 재내보내기) 이후 그리고 build-content(콘텐츠 시딩은 테마가 활성화되어 메뉴 위치를 찾을 수 있어야 함) 이전에 실행됩니다.
이 스킬은 호출 명령에서 이미 설정된 다음 변수를 필요로 합니다.
BUILD_DIR— 빌드 디렉토리의 절대 경로(build-scaffold섹션 2에서 설정)WP— WP-CLI 명령 접두사(예:wp --path=$BUILD_DIR또는 Docker에 해당하는 것,build-scaffold섹션 4에서 설정)NL_PROMPT— 사용자의 자연어 사이트 설명 문자열SITE_TITLE— NL 프롬프트에서 파생된 사이트 제목(이 스킬 전에 호출 명령에서 설정)
섹션 1: WP.org 테마 API 쿼리
FSE 블록 테마 풀을 위해 WP.org Themes API v1.2를 쿼리합니다. 필터링에는 full-site-editing 태그를 사용하십시오. 이것은 FSE/블록 테마에 대한 표준 공개 신호입니다. search와 tag 매개변수를 함께 사용하지 마십시오: API는 search가 있으면 태그를 무시합니다. Claude는 풀을 가져온 후 문맥 내에서 테마 관련성을 평가합니다.
echo "[Build] FSE 테마 풀을 위해 WP.org Themes API 쿼리 중..."
# 중요 안티패턴: ?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 "[Build] WP.org API가 평가할 $THEME_COUNT개의 FSE 테마를 반환했습니다."
else
echo "[Build] WP.org API가 3개 미만의 테마를 반환했습니다($THEME_COUNT). 큐레이트된 목록으로 대체합니다."
fi
else
echo "[Build] WP.org API를 사용할 수 없음 — 큐레이트된 테마 목록 사용"
fi
섹션 2: 테마 평가 및 선택
Claude는 API JSON 응답을 읽고 NL_PROMPT에 대해 각 테마를 평가합니다. API가 실행 가능한 풀을 반환한 경우 Claude는 관련성, 인기도, 평점을 사용하여 최적의 일치 항목을 선택합니다. API가 실패했거나 너무 적은 결과를 반환한 경우 Claude는 NL_PROMPT의 사이트 카테고리에 따라 큐레이트된 대체 목록에서 선택합니다.
점수 기준 (우선순위 순):
NL_PROMPT에 설명된 사이트 유형에 대한 이름, 설명 및 태그 관련성active_installs— 인기도 신호(높을수록 좋음)rating— 품질 신호(높을수록 좋음)
클래식 테마는 절대 선택되지 않습니다. 다른 지표에서 점수가 더 높아도 마찬가지입니다.
if [ "$API_AVAILABLE" = "true" ]; then
echo "[Build] NL 프롬프트에 대해 FSE 테마 평가 중: \"$NL_PROMPT\""
echo "[Build] 다음 파일에서 테마 읽는 중: $FSE_THEMES_FILE"
# Claude는 FSE 테마 JSON을 읽고 각 테마를 평가합니다:
# - themes[].name: 표시 이름
# - themes[].slug: WP.org 설치 슬러그
# - 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="<API 결과에서 Claude가 선택한 슬러그>"
THEME_NAME="<API 결과에서 Claude가 선택한 표시 이름>"
else
# 큐레이트된 대체 목록 — 사이트 카테고리를 알려진 FSE 호환 테마 슬러그에 매핑
# 이 테마들은 WP.org에서 유지 관리되는 확인된 FSE 블록 테마입니다.
# 테마가 WP.org에서 제거되면 이 목록을 업데이트하십시오.
#
# 카테고리 → 슬러그 매핑 (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가 큐레이트된 대체 목록에서 선택한 슬러그>"
THEME_NAME="<선택된 큐레이트 테마의 표시 이름>"
fi
echo "[Build] 선택된 테마: $THEME_NAME ($THEME_SLUG)"
섹션 3: 테마 설치 및 활성화
WP-CLI를 사용하여 선택한 테마를 설치하고 활성화합니다. 설치에 실패하면 대체 후보를 시도합니다. 설치 후 theme.json을 확인하여 항상 FSE 호환성을 검증합니다. 경고 후 계속 진행 — 테마 실패로 빌드를 중단하지 마십시오.
echo "[Build] 테마 설치 중: $THEME_SLUG..."
install_theme() {
local slug="$1"
if $WP theme install "$slug" --activate 2>&1; then
echo "[Build] 테마 설치 및 활성화됨: $slug"
# FSE 검증 — theme.json 존재 확인
# Claude가 FSE 풀에서 선택했으므로 이는 2차 확인입니다.
# theme.json이 하위 디렉토리에 있거나 다른 이름인 경우 false negative 가능성 있음.
if [ -f "$BUILD_DIR/wp-content/themes/$slug/theme.json" ]; then
echo "[Build] FSE 확인됨: theme.json을 찾았습니다."
else
echo "[Build] 경고: theme.json을 찾을 수 없음 — 테마가 FSE와 호환되지 않을 수 있습니다."
echo "[Build] 계속 진행 — 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 "[Build] 테마 설치 및 활성화됨: $slug (v$THEME_VERSION)"
return 0
else
echo "[Build] 경고: 슬러그의 테마 설치 실패: $slug"
THEME_INSTALLED=false
return 1
fi
}
# 시도 1: API에서 선택했거나 큐레이트된 테마 설치
if ! install_theme "$THEME_SLUG"; then
# 시도 2: API 선택 테마가 실패한 경우, 큐레이트된 대체 테마 시도
if [ "$API_AVAILABLE" = "true" ]; then
echo "[Build] 사이트 카테고리에 대한 큐레이트된 대체 테마 시도..."
# Claude가 NL_PROMPT 사이트 카테고리에서 큐레이트된 대체 슬러그 결정
# (섹션 2 큐레이트 목록 참조) 후 재시도
FALLBACK_SLUG="twentytwentyfour" # Claude가 해당하는 경우 카테고리별 슬러그로 대체
if ! install_theme "$FALLBACK_SLUG"; then
# 시도 3: 최후의 수단 — twentytwentyfour (WordPress.org에서 유지 관리)
if [ "$FALLBACK_SLUG" != "twentytwentyfour" ]; then
echo "[Build] 최후의 대체 수단 시도: twentytwentyfour..."
if ! install_theme "twentytwentyfour"; then
# 최종 대체 — 경고 로그 기록 후 WP 기본 테마로 계속 진행
echo "[Build] 경고: 모든 테마 설치 시도가 실패했습니다."
echo "[Build] 경고: WordPress 기본 테마로 빌드를 계속합니다."
THEME_SLUG="default"
THEME_NAME="WordPress Default"
THEME_VERSION="unknown"
THEME_INSTALLED=false
fi
else
# twentytwentyfour가 이미 실패함 — 기본값으로 계속
echo "[Build] 경고: 모든 테마 설치 시도가 실패했습니다."
echo "[Build] 경고: WordPress 기본 테마로 빌드를 계속합니다."
THEME_SLUG="default"
THEME_NAME="WordPress Default"
THEME_VERSION="unknown"
THEME_INSTALLED=false
fi
fi
else
# 큐레이트된 테마 실패 — 최후의 수단으로 twentytwentyfour 시도
if [ "$THEME_SLUG" != "twentytwentyfour" ]; then
echo "[Build] 최후의 대체 수단 시도: twentytwentyfour..."
if ! install_theme "twentytwentyfour"; then
echo "[Build] 경고: 모든 테마 설치 시도가 실패했습니다."
echo "[Build] 경고: WordPress 기본 테마로 빌드를 계속합니다."
THEME_SLUG="default"
THEME_NAME="WordPress Default"
THEME_VERSION="unknown"
THEME_INSTALLED=false
fi
else
echo "[Build] 경고: 모든 테마 설치 시도가 실패했습니다."
echo "[Build] 경고: WordPress 기본 테마로 빌드를 계속합니다."
THEME_SLUG="default"
THEME_NAME="WordPress Default"
THEME_VERSION="unknown"
THEME_INSTALLED=false
fi
fi
fi
# 임시 API 응답 파일 정리
rm -f "$FSE_THEMES_FILE"
섹션 4: 사이트 제목 업데이트
NL_PROMPT에 설명된 사이트와 일치하도록 WordPress 사이트 제목과 태그라인을 업데이트합니다. 사이트 제목은 이미 build-scaffold WP 설치 중에 설정되었지만(--title="$SITE_TITLE"), 이 단계에서는 NL 프롬프트에서 생성된 컨텍스트 설명으로 태그라인을 설정할 수 있습니다.
echo "[Build] 사이트 제목 및 태그라인 설정 중..."
# 사이트 제목 업데이트 (build-scaffold --title과 이미 일치할 수 있지만, 확인을 위해 업데이트)
$WP option update blogname "$SITE_TITLE" 2>&1
# Claude가 NL_PROMPT에서 간결한 태그라인(한 줄, 따옴표 없음) 생성
# 예시:
# NL_PROMPT: "a portfolio site for a freelance photographer"
# → 태그라인: "Capturing moments that matter"
#
# NL_PROMPT: "a restaurant website for an Italian bistro in Sydney"
# → 태그라인: "Authentic Italian flavours in the heart of Sydney"
#
# Claude가 SITE_TAGLINE을 생성된 태그라인으로 설정한 후:
SITE_TAGLINE="<NL_PROMPT에서 Claude가 생성한 태그라인>"
$WP option update blogdescription "$SITE_TAGLINE" 2>&1
echo "[Build] 사이트 제목 설정됨: $SITE_TITLE"
echo "[Build] 사이트 태그라인 설정됨: $SITE_TAGLINE"
구현 참고 사항
파이프라인 위치: 이 스킬은 NL 빌드 파이프라인에서 build-mcp 섹션 2(MCP 어댑터 활성화, 데이터베이스 재내보내기) 이후 그리고 build-content 이전에 엄격하게 실행됩니다. 콘텐츠 시딩 전에 테마가 활성화되어야 합니다. build-content가 $WP menu location list를 사용하여 활성 테마의 탐색 위치를 찾으려면 대상 테마가 이미 설치 및 활성화되어 있어야 합니다.
Docker MySQL 컨테이너: build-scaffold 섹션 3의 임시 Docker MySQL 컨테이너는 이 스킬이 실행될 때 여전히 실행 중이어야 합니다. WP-CLI 테마 설치는 WordPress 옵션 테이블(활성 테마 슬러그)에 씁니다. build-scaffold 섹션 3에 설정된 EXIT 트랩은 전체 빌드 세션 동안 활성 상태로 유지되며 전체 명령이 종료될 때만 실행됩니다 — 스킬 호출 사이에는 실행되지 않습니다.
출력 변수: 이 스킬에 의해 설정되고 다운스트림 스킬(build-content, build-setup)에서 사용되는 변수:
THEME_SLUG— 설치된 테마 슬러그(예:twentytwentyfour,flavor)THEME_NAME— 표시 이름(예:Twenty Twenty-Four,Flavor)THEME_VERSION— 설치된 버전 문자열(예:1.3, 감지 불가능한 경우unknown)THEME_INSTALLED— 설치 성공 시true, 모든 대체 수단 실패 시false
큐레이트된 대체 목록 유지 관리: 큐레이트된 목록은 사이트 카테고리를 WP.org의 알려진 FSE 블록 테마에 매핑합니다. 큐레이트된 테마 슬러그가 WP.org에서 제거되어( wp theme install이 "찾을 수 없음"으로 실패) 이 목록을 현재 FSE 호환 대체 테마로 업데이트하십시오. twentytwentyfour는 보장된 최후의 대체 수단입니다 — WordPress.org 핵심 팀에서 유지 관리하며 제거되지 않습니다.
설치 후 사용자 정의 없음(고정 결정): CONTEXT.md에 기록된 사용자 결정에 따라, 설치 후 theme.json 재정의, 하위 테마 또는 글로벌 스타일 수정이 적용되지 않습니다. 테마는 WP.org에서 제공되는 그대로 설치 및 활성화됩니다. 내장 디자인이 그대로 제공됩니다.
FSE 검증 신뢰성: theme.json 확인은 2차 확인입니다 — 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 출력