---
name: theme-harvest
description: Copy template and template part edits saved in the Site Editor on a local site back into a block theme's files, translatable and validated. Use after editing a theme's templates or parts in the Site Editor, e.g. while fixing a /theme-review checklist.
---

# Theme Harvest Skill

Takes the templates and template parts a designer edited and saved in the Site Editor on a local site, and writes them back into the theme's files in the repo, in the form the theme review expects.

## Usage

```
/theme-harvest themeslug                  # every saved template and part of the theme
/theme-harvest themeslug single-product   # one template or part
```

## Step 1: Find the local site and its WP-CLI

Ask which local site has the edits if it isn't clear from context. Use that site's own WP-CLI, which knows its database:

- **Studio:** `studio wp …` in the site folder
- **Local:** the site's "Open site shell", or `wp` with `--path=<site>/app/public` and PHP's `mysqli.default_socket` set to the site's MySQL socket
- **wp-env:** `npx wp-env run cli wp …`

Check that the theme is active and whether the site's theme folder is the repo folder itself (a symlink or the same inode). If it is a copy, the files you write in the repo won't show on the site until the copy is updated.

## Step 2: List what was saved

```bash
wp post list --post_type=wp_template,wp_template_part --post_status=publish \
  --fields=ID,post_type,post_name,post_modified --format=table
```

Keep the posts that belong to the theme (their `wp_theme` term is the theme slug). A template the designer saved while editing may also have saved a page: the Cart and Checkout templates show the page's own content, so saving them can save the Cart or Checkout page too. Check `page` posts modified at the same time, and tell the designer if one changed. That's site content, not a theme file, so don't harvest it.

## Step 3: Compare and check

For each saved template or part, export its content (`wp post get <ID> --field=post_content`) and compare it with what the theme file renders now:

- Summarise the differences in plain words (e.g. "the collection is now 3 columns and lets title and price wrap"), so the designer can confirm they are the intended edits.
- Compare the edited template with its siblings (e.g. Product Catalog, Product Search Results and Products by Attribute should share their product card, pagination and heading setup) and point out inconsistencies before harvesting. Ask whether each difference is intended.
- If the saved version only differs in editor noise (`queryId` numbers, `isDescendentOfQueryLoop`), say there's nothing to harvest.

## Step 4: Write the files

Templates reference a hidden pattern (`templates/<slug>.html` holds `<!-- wp:pattern {"slug":"<theme>/<slug>"} /-->`); write the saved content into that pattern file. If the template has no pattern yet, create `patterns/<slug>.php` and point the template at it. Parts are written to `parts/<slug>.html`; if a part has translatable text, move that text into a hidden pattern the part references.

While writing:
- Remove `"theme":"<theme>"` from `wp:template-part` blocks (the editor adds it).
- Make every user-facing word translatable: `esc_html_e( 'Text', '<text-domain>' )` for text, `esc_attr_e()` for attributes, and `printf( esc_html__( 'Text %1$swith a link%2$s', '<text-domain>' ), '<a href="#">', '</a>' )` with a `/* translators: … */` comment for text containing links. Trim whitespace around the text (markup pasted from WooCommerce often starts text on a new line). Symbols like "+" don't need translation.
- Keep `<?php` directly after the opening tag (`<p><?php esc_html_e( … ); ?></p>`), not on its own line.
- Remove every `"patternName"` from block metadata and keep the block's `name`.
- Give the pattern a real title (`Title: Product Search Results`, not `product-search-results`) and `Inserter: no`.
- Don't change anything the designer didn't change.

## Step 5: Verify

1. `php -l` on each changed PHP file.
2. **Same output:** render the new pattern with PHP (stub the WordPress i18n and escaping functions, or `wp eval` with `do_blocks()`) and compare with the saved content, ignoring whitespace between tags and the removed `theme`/`patternName` attributes. They must match.
3. **Valid blocks:** parse the rendered pattern with `wp.blocks.parse()` in a Site Editor tab on the local site. No block may be invalid.
4. **New pattern files:** clear the theme's pattern cache so WordPress registers them: `wp eval 'wp_get_theme()->delete_pattern_cache();'`.
5. After any `theme.json` or `style.css` change: `npm run validate:theme -- <theme>`.

## Step 6: Commit and report

Commit each template or part separately (`<Theme>: <Template> template adjustments`), listing the harvested edits in the message. Push only when the designer asks.

If the harvest fixes items in a posted `/theme-review` author checklist, mark them there: fetch the live comment body, strike the item and add "Fixed in <commit>", and PATCH it back without touching other lines.

Tell the designer that their saved version still overrides the theme file on the local site. It's identical right after the harvest, but it will hide later changes to the file. They can reset it in the Site Editor (Templates, the template's "Reset" action) once they're done editing.
