From wordpress-expert
Generates SETUP.md with priority-ordered plugin/theme configs and content guidance for Local WP WordPress imports, updates build.json with NL metadata.
npx claudepluginhub dr-robert-li/cowork-wordpress-expertThis skill uses the workspace's default tool permissions.
Generate `SETUP.md` — the user's post-import configuration and content replacement guide — and update `build.json` with NL-specific metadata. This skill runs after `build-content` and before zip packaging.
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Generates original PNG/PDF visual art via design philosophy manifestos for posters, graphics, and static designs on user request.
Generate SETUP.md — the user's post-import configuration and content replacement guide — and update build.json with NL-specific metadata. This skill runs after build-content and before zip packaging.
Input variables (set by build-theme and build-content):
| Variable | Source | Description |
|---|---|---|
BUILD_DIR | build-scaffold | Absolute path to the build working directory |
NL_PROMPT | COMMAND.md Section 1 | Original natural language site description |
THEME_SLUG | build-theme | Installed theme slug |
THEME_NAME | build-theme | Human-readable theme name |
THEME_VERSION | build-theme | Installed theme version string |
THEME_INSTALLED | build-theme | Boolean — true if theme installed successfully |
INSTALLED_PLUGINS | build-content | Array of slug:name:version for successfully installed plugins |
FAILED_PLUGINS | build-content | Array of slugs that failed to install or activate |
PAGES_CREATED | build-content | Integer count of pages created |
POSTS_CREATED | build-content | Integer count of posts created |
MENU_ASSIGNED | build-content | Boolean — true if navigation menu was assigned to a theme location |
MENU_LOCATION | build-content | The theme location name used (or empty string if unassigned) |
Write $BUILD_DIR/SETUP.md using the full context available — installed plugins, theme, page count, and NL prompt — to produce a priority-ordered setup guide the user can follow immediately after importing the site into Local WP.
echo "[Build] Generating SETUP.md..."
# ── Build the What's Installed section ────────────────────────────────────────
SETUP_FILE="$BUILD_DIR/SETUP.md"
# Start writing SETUP.md
cat > "$SETUP_FILE" << 'SETUP_HEADER'
# Setup Guide
This guide walks you through configuring your new WordPress site after importing
it into Local WP. Items are ordered by priority — complete the Critical steps
first, then work through Important and Optional at your own pace.
---
## What's Installed
SETUP_HEADER
# Theme entry
echo "- **Theme:** ${THEME_NAME} (v${THEME_VERSION})" >> "$SETUP_FILE"
echo "" >> "$SETUP_FILE"
# Plugin list
if [ ${#INSTALLED_PLUGINS[@]} -gt 0 ]; then
echo "- **Plugins:**" >> "$SETUP_FILE"
for plugin_entry in "${INSTALLED_PLUGINS[@]}"; do
# Format: slug:name:version
PLUGIN_SLUG=$(echo "$plugin_entry" | cut -d: -f1)
PLUGIN_NAME=$(echo "$plugin_entry" | cut -d: -f2)
PLUGIN_VER=$(echo "$plugin_entry" | cut -d: -f3)
# Claude generates a one-line purpose for each plugin based on the plugin slug and name
PLUGIN_PURPOSE="<one-line description of what ${PLUGIN_NAME} does — generated by Claude from knowledge of the plugin>"
echo " - **${PLUGIN_NAME}** (v${PLUGIN_VER}) — ${PLUGIN_PURPOSE}" >> "$SETUP_FILE"
done
echo "" >> "$SETUP_FILE"
fi
# Failed plugins (if any)
if [ ${#FAILED_PLUGINS[@]} -gt 0 ]; then
echo "- **Plugins That Failed to Install:**" >> "$SETUP_FILE"
for slug in "${FAILED_PLUGINS[@]}"; do
echo " - ${slug} — installation was attempted but failed during build" >> "$SETUP_FILE"
done
echo "" >> "$SETUP_FILE"
fi
Next, write the priority-ordered action list. This is an AI judgment task — Claude generates the actual step-by-step instructions for each plugin based on Claude's knowledge of that plugin's settings workflow, using the NL prompt context to determine what matters most for this particular site.
# ── Build the What to Do Next section ────────────────────────────────────────
cat >> "$SETUP_FILE" << 'SETUP_NEXT'
---
## What to Do Next (Priority Order)
SETUP_NEXT
# ── CRITICAL items ────────────────────────────────────────────────────────────
echo "### Critical" >> "$SETUP_FILE"
echo "" >> "$SETUP_FILE"
STEP_NUM=1
# For each installed plugin that requires configuration, Claude generates
# step-by-step instructions with full WordPress admin navigation paths.
# Example pattern for WPForms Lite:
#
# echo "${STEP_NUM}. **Configure WPForms — create your contact form**" >> "$SETUP_FILE"
# cat >> "$SETUP_FILE" << 'EOF'
# Go to: **WPForms > Add New**
# Steps:
# 1. Click "Select a Template" and choose **Simple Contact Form**
# 2. Click "Use Template" — the form builder opens
# 3. (Optional) Add or remove fields by dragging from the left panel
# 4. Click **Save** in the top right
# 5. Go to **Pages > Contact > Edit**
# 6. Add a new block, search for "WPForms", and select the WPForms block
# 7. Choose your newly created form from the dropdown
# 8. Click **Update** to save the page
# EOF
# STEP_NUM=$((STEP_NUM + 1))
# Claude generates equivalent blocks for every plugin in INSTALLED_PLUGINS
# that requires user configuration. Plugins that work without setup (e.g.,
# a caching plugin that activates silently) can be documented under Important
# or omitted if no action is needed.
# ── Contact page placeholder replacement (always Critical) ────────────────────
echo "${STEP_NUM}. **Replace Contact page placeholder info**" >> "$SETUP_FILE"
cat >> "$SETUP_FILE" << 'CONTACT_STEP'
Go to: **Pages > Contact > Edit**
Replace the following placeholder content with your real details:
- The fictional business name in the page heading
- The fictional street address (e.g., "123 Example Street, Sample City")
- The fictional phone number
- The fictional email address
- Any fictional business hours or location details
CONTACT_STEP
STEP_NUM=$((STEP_NUM + 1))
# ── IMPORTANT items ───────────────────────────────────────────────────────────
echo "" >> "$SETUP_FILE"
echo "### Important" >> "$SETUP_FILE"
echo "" >> "$SETUP_FILE"
# About page content replacement
echo "${STEP_NUM}. **Update About page content**" >> "$SETUP_FILE"
cat >> "$SETUP_FILE" << 'ABOUT_STEP'
Go to: **Pages > About > Edit**
Replace the following placeholder content:
- The fictional business/person name and biography
- Any fictional team member descriptions
- The placeholder headshot or profile image (upload your own via the Media block)
- Any fictional credentials, history, or origin story
ABOUT_STEP
STEP_NUM=$((STEP_NUM + 1))
# Home page content replacement
echo "${STEP_NUM}. **Update Home page hero and intro content**" >> "$SETUP_FILE"
cat >> "$SETUP_FILE" << 'HOME_STEP'
Go to: **Pages > Home > Edit**
Replace the following placeholder content:
- The hero heading and tagline (make it specific to your business or offer)
- The hero background or featured image (upload via the Cover/Image block)
- The introductory paragraph describing what you do
- Any call-to-action button labels and links
HOME_STEP
STEP_NUM=$((STEP_NUM + 1))
# Additional pages based on site type — Claude generates page-specific guidance
# for each page in PAGES_CREATED beyond Home, About, Contact. Examples:
#
# Portfolio page:
# echo "${STEP_NUM}. **Add your real work to the Portfolio page**" >> "$SETUP_FILE"
# ...
# STEP_NUM=$((STEP_NUM + 1))
#
# Services page:
# echo "${STEP_NUM}. **Update Services page with your actual offerings**" >> "$SETUP_FILE"
# ...
# STEP_NUM=$((STEP_NUM + 1))
#
# Claude uses NL_PROMPT context to determine which additional pages exist
# and what placeholder content they contain, then writes targeted guidance.
# Any additional plugin configuration that falls under Important (not Critical)
# Claude adds steps here for plugins that need setup but aren't site-breaking
# if left unconfigured (e.g., SEO plugin configuration, gallery settings)
# ── OPTIONAL items ────────────────────────────────────────────────────────────
echo "" >> "$SETUP_FILE"
echo "### Optional" >> "$SETUP_FILE"
echo "" >> "$SETUP_FILE"
# Sample posts replacement
echo "${STEP_NUM}. **Add your own blog posts to replace sample content**" >> "$SETUP_FILE"
cat >> "$SETUP_FILE" << 'POSTS_STEP'
The sample posts demonstrate how your theme renders blog content. They use
realistic but fictional topics related to your site's subject matter.
Go to: **Posts > All Posts** to edit the existing samples or add new ones.
You can delete the sample posts once you have published your own content.
POSTS_STEP
STEP_NUM=$((STEP_NUM + 1))
# Placeholder image replacement
echo "${STEP_NUM}. **Replace placeholder images with your own photos**" >> "$SETUP_FILE"
cat >> "$SETUP_FILE" << 'IMAGES_STEP'
Solid-color placeholder images were generated during the build to show
layout intent. Replace them with your own images:
Go to: **Media > Add New** to upload your photos
Then edit each page/post and swap the placeholder image blocks for your uploads.
IMAGES_STEP
STEP_NUM=$((STEP_NUM + 1))
# Menu assignment if not automatically assigned (FSE block theme edge case)
if [ "$MENU_ASSIGNED" = "false" ] || [ "$MENU_ASSIGNED" = "" ]; then
echo "${STEP_NUM}. **Assign navigation menu in the Site Editor**" >> "$SETUP_FILE"
cat >> "$SETUP_FILE" << 'MENU_STEP'
Your navigation menu was created during the build but could not be assigned
to a theme location automatically (this is expected for block themes).
Go to: **Appearance > Editor > Navigation**
Select "Primary Menu" and place it in your header navigation area.
MENU_STEP
STEP_NUM=$((STEP_NUM + 1))
fi
# Finalize SETUP.md
echo "---" >> "$SETUP_FILE"
echo "" >> "$SETUP_FILE"
echo "*Generated by WordPress Expert Plugin — CoWork Build System*" >> "$SETUP_FILE"
SETUP_ITEM_COUNT=$((STEP_NUM - 1))
echo "[Build] SETUP.md generated (${SETUP_ITEM_COUNT} setup items)"
Implementation notes for Claude:
INSTALLED_PLUGINS, Claude generates verbose, step-by-step instructions using its knowledge of that plugin's settings workflow. Instructions must include full WP admin navigation paths (e.g., "Go to WPForms > Add New > Select Contact Form template > Save > Copy shortcode > Edit Contact page > Add shortcode block").NL_PROMPT to determine which setup items are Critical vs Important. For a photography portfolio site, replacing portfolio images is Critical. For a restaurant, configuring a reservation plugin is Critical.Read the existing build.json (created by build-scaffold Section 6) and add NL-specific fields. Uses the same Python3 JSON parsing pattern established in build-mcp Section 4.
echo "[Build] Updating build.json with NL metadata..."
BUILD_JSON="$BUILD_DIR/build.json"
# Build arrays for JSON serialization
INSTALLED_JSON=""
for plugin_entry in "${INSTALLED_PLUGINS[@]}"; do
PLUGIN_SLUG=$(echo "$plugin_entry" | cut -d: -f1)
PLUGIN_NAME=$(echo "$plugin_entry" | cut -d: -f2)
PLUGIN_VER=$(echo "$plugin_entry" | cut -d: -f3)
if [ -n "$INSTALLED_JSON" ]; then
INSTALLED_JSON="${INSTALLED_JSON},"
fi
INSTALLED_JSON="${INSTALLED_JSON}{\"slug\":\"${PLUGIN_SLUG}\",\"name\":\"${PLUGIN_NAME}\",\"version\":\"${PLUGIN_VER}\",\"installed\":true}"
done
FAILED_JSON=""
for slug in "${FAILED_PLUGINS[@]}"; do
if [ -n "$FAILED_JSON" ]; then
FAILED_JSON="${FAILED_JSON},"
fi
FAILED_JSON="${FAILED_JSON}\"${slug}\""
done
# Write Python script to temp file (same pattern as build-content image generator)
NL_META_SCRIPT="/tmp/update_build_json_$$.py"
cat > "$NL_META_SCRIPT" << PYEOF
import json, sys
build_file = sys.argv[1]
nl_prompt = sys.argv[2]
theme_slug = sys.argv[3]
theme_name = sys.argv[4]
theme_version = sys.argv[5]
theme_installed = sys.argv[6] == 'true'
pages_created = int(sys.argv[7])
posts_created = int(sys.argv[8])
menu_assigned = sys.argv[9] == 'true'
installed_json = sys.argv[10]
failed_json = sys.argv[11]
with open(build_file) as f:
data = json.load(f)
data['mode'] = 'nl'
data['nl_prompt'] = nl_prompt
data['theme'] = {
'slug': theme_slug,
'name': theme_name,
'version': theme_version,
'installed': theme_installed
}
data['plugins'] = json.loads('[' + installed_json + ']') if installed_json else []
data['content'] = {
'pages_created': pages_created,
'posts_created': posts_created,
'menu_assigned': menu_assigned
}
if failed_json:
data['failed_plugins'] = json.loads('[' + failed_json + ']')
with open(build_file, 'w') as f:
json.dump(data, f, indent=2)
print('[Build] build.json updated with NL metadata')
PYEOF
python3 "$NL_META_SCRIPT" \
"$BUILD_JSON" \
"$NL_PROMPT" \
"$THEME_SLUG" \
"$THEME_NAME" \
"$THEME_VERSION" \
"${THEME_INSTALLED:-true}" \
"$PAGES_CREATED" \
"$POSTS_CREATED" \
"${MENU_ASSIGNED:-false}" \
"$INSTALLED_JSON" \
"$FAILED_JSON"
# Cleanup temp script
rm -f "$NL_META_SCRIPT"
build.json after NL metadata update:
{
"build_id": "nl-photography-portfolio-20260220-143022",
"mode": "nl",
"nl_prompt": "a portfolio site for a freelance photographer",
"wp_version": "6.7",
"php_version": "8.2",
"site_url": "http://localhost",
"site_title": "a portfolio site for a freelance photographer",
"created_at": "2026-02-20T14:30:22Z",
"theme": {
"slug": "blocksy",
"name": "Blocksy",
"version": "2.0.50",
"installed": true
},
"plugins": [
{ "slug": "envira-gallery-lite", "name": "Envira Gallery Lite", "version": "1.9.0", "installed": true },
{ "slug": "wpforms-lite", "name": "WPForms Lite", "version": "1.9.0", "installed": true }
],
"content": {
"pages_created": 4,
"posts_created": 3,
"menu_assigned": false
},
"failed_plugins": [],
"mcp_adapter": {
"included": true,
"activated": true,
"version": "0.4.1"
}
}
Append NL-specific lines to the build summary output. This runs after build-scaffold Section 7 (base summary) and build-mcp Section 5 (MCP extension) to add NL build details.
# ── NL Build Summary Extension ────────────────────────────────────────────────
# Count plugins
INSTALLED_COUNT=${#INSTALLED_PLUGINS[@]}
FAILED_COUNT=${#FAILED_PLUGINS[@]}
# Menu status string
if [ "$MENU_ASSIGNED" = "true" ] && [ -n "$MENU_LOCATION" ]; then
MENU_STATUS="assigned to '${MENU_LOCATION}'"
else
MENU_STATUS="created but not assigned (see SETUP.md)"
fi
echo ""
echo "[Build] ── NL Build Details ──────────────────"
echo "[Build] Prompt: \"${NL_PROMPT}\""
echo "[Build] Theme: ${THEME_NAME} (${THEME_SLUG} v${THEME_VERSION})"
echo "[Build] Plugins: ${INSTALLED_COUNT} installed, ${FAILED_COUNT} failed"
echo "[Build] Content: ${PAGES_CREATED} pages, ${POSTS_CREATED} posts"
echo "[Build] Menu: ${MENU_STATUS}"
echo "[Build] Guide: SETUP.md included in zip"
echo ""
Example output for a photography portfolio build:
[Build] ── NL Build Details ──────────────────
[Build] Prompt: "a portfolio site for a freelance photographer"
[Build] Theme: Blocksy (blocksy v2.0.50)
[Build] Plugins: 2 installed, 0 failed
[Build] Content: 4 pages, 3 posts
[Build] Menu: created but not assigned (see SETUP.md)
[Build] Guide: SETUP.md included in zip