---
name: wordpress
description: "Use when building or hardening WordPress sites or WooCommerce stores and treating WordPress as the product rather than just writing PHP — block themes with theme.json, plugins with block.json and proper hooks, wp-config security hardening, performance (object cache, asset loading, autoloaded options), and WP-CLI operations. NOT a Laravel app (that is `laravel`)."
tags: [wordpress, woocommerce, block-themes, wp-cli, php, security-hardening, performance]
recommends: [php, secure-coding, performance, mysql, shopify]
origin: risco
---
# WordPress
You are building the WordPress application layer — themes, plugins, the dashboard/CLI surface, security, and stores — for someone treating WordPress as the product. Know the difference between a `functions.php` hack and a real plugin. Refuse to paste secrets into the dashboard file editor. Pick block themes over page builders by default. Reach for `wp` before clicking through wp-admin.
This is not generic PHP. If there is no WordPress API in sight (value objects, Composer/PSR-4, PHPStan), that is [php](../php/SKILL.md). A Laravel app is [laravel](../laravel/SKILL.md).
## Version & runtime targeting
Target current. Stale version assumptions are the most common way WP code rots.
- **WordPress 6.9** (released 2025-12-02) is current; it refines speculative loading and supports PHP 8.5. WP 6.8 ("Cecil", 2025-04-15) added bcrypt password hashing and speculative loading. *Why: features below assume 6.6+ APIs (`wp_enqueue_block_style`, theme.json v3).*
- **PHP 8.4 is the recommended runtime for 2026.** WP 6.9 fully supports PHP 8.5; WP 6.8+ fully supports 8.4; WP 6.4+ supports 8.3. **Never target PHP 7.x or 8.0–8.2 for new code — all EOL.** *Why: writing for a dead runtime ships deprecation bugs the host will eventually refuse to run.*
- **theme.json v3** is the schema for new block themes (WP 6.6+). Locally set `WP_DEVELOPMENT_MODE` to `all` so theme.json edits are not cached for 30+ seconds. *Why: without it you will edit theme.json, see nothing change, and waste an hour.*
```php
// wp-config.php — local dev only, never on production
define( 'WP_DEVELOPMENT_MODE', 'all' );
define( 'WP_DEBUG', true );
define( 'SCRIPT_DEBUG', true );
```
## Decision: how heavy is the change?
Pick the lightest artifact that survives an update. The failure mode is everyone reaching for `functions.php` or editing files that get overwritten.
| You need to… | Artifact | Do NOT |
| --- | --- | --- |
| One-line tweak, site-specific behavior | mu-plugin in `wp-content/mu-plugins/` | dump it in the active theme's `functions.php` |
| Change look of a third-party theme | **child theme** | edit the parent theme — updates wipe it |
| Reusable feature, hooks, blocks, CPTs | **standalone plugin** | hide app logic in `functions.php` |
| Full custom front end | **block theme** + theme.json v3 | reach for a page builder for structural layout |
| Sell products | block theme + **WooCommerce** | hand-roll a cart |
## Block themes
A block theme is `theme.json` + HTML templates in `templates/` and `parts/`. Start from a v3 skeleton:
```json
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"settings": {
"appearanceTools": true,
"color": {
"palette": [
{ "slug": "base", "color": "#ffffff", "name": "Base" },
{ "slug": "contrast", "color": "#111111", "name": "Contrast" }
]
},
"typography": {
"fluid": true,
"fontFamilies": [
{ "fontFamily": "system-ui, sans-serif", "slug": "system", "name": "System" }
]
},
"layout": { "contentSize": "640px", "wideSize": "1100px" }
},
"styles": {
"color": { "background": "var(--wp--preset--color--base)", "text": "var(--wp--preset--color--contrast)" }
}
}
```
Templates resolve by hierarchy: `templates/index.html` is the fallback; `single.html`, `archive.html`, `page.html`, `404.html` override it. Reusable chunks live in `parts/` (`header.html`, `footer.html`).
Register patterns by dropping PHP-headered HTML in `patterns/`; they appear in the inserter automatically. Enqueue CSS **per block** so it only loads when the block renders:
```php
add_action( 'init', function () {
wp_enqueue_block_style( 'core/group', array(
'handle' => 'mytheme-group',
'src' => get_theme_file_uri( 'assets/blocks/group.css' ),
'path' => get_theme_file_path( 'assets/blocks/group.css' ),
) );
} );
```
Rule: never hand-write ``/`