Communitygithub.com

dr-robert-li/cowork-wordpress-expert

Generate SETUP.md with priority-ordered plugin configuration and content replacement guidance, and update build.json with NL-specific metadata

What is cowork-wordpress-expert?

cowork-wordpress-expert is a Claude Code agent skill that generate SETUP.md with priority-ordered plugin configuration and content replacement guidance, and update build.json with NL-specific metadata.

Works with✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/dr-robert-li/cowork-wordpress-expert/tree/HEAD/skills/build-setup

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

Build Setup Skill

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):

VariableSourceDescription
BUILD_DIRbuild-scaffoldAbsolute path to the build working directory
NL_PROMPTCOMMAND.md Section 1Original natural language site description
THEME_SLUGbuild-themeInstalled theme slug
THEME_NAMEbuild-themeHuman-readable theme name
THEME_VERSIONbuild-themeInstalled theme version string
THEME_INSTALLEDbuild-themeBoolean — true if theme installed successfully
INSTALLED_PLUGINSbuild-contentArray of slug:name:version for successfully installed plugins
FAILED_PLUGINSbuild-contentArray of slugs that failed to install or activate
PAGES_CREATEDbuild-contentInteger count of pages created
POSTS_CREATEDbuild-contentInteger count of posts created
MENU_ASSIGNEDbuild-contentBoolean — true if navigation menu was assigned to a theme location
MENU_LOCATIONbuild-contentThe theme location name used (or empty string if unassigned)

Section 1: SETUP.md Generation

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:

  • Plugin instructions are an AI judgment task. For each plugin in 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").
  • Context drives priority. Claude reads 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.
  • Page-by-page coverage. Every page created by build-content gets a dedicated entry with specific guidance on what placeholder content it contains.
  • No generic instructions. All guidance is specific to the plugin and site type — not generic "configure your plugins" advice.

Section 2: build.json NL Metadata Update

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"
  }
}

Section 3: Build Summary Extension

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

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Related Skills