--- 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 ``/`