Skip to main content

wordpress

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`).

Aller à l'installation

Informations de source

Dépôt
ericrisco/rsc-harness
Dernière activité de la source
29 juillet 2026 à 23:40
Langue détectée de SKILL.md
anglais
Étoiles
110
Forks
9

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Explorateur de fichiers
7 fichiers

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
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 `<link>`/`<script>` tags in templates — the browser cannot cache them and you lose dependency management. Always enqueue. And never edit a parent theme directly; make a child theme. ## Plugins A plugin is a folder with a headered main file. That header is what makes it a plugin: ```php <?php /** * Plugin Name: Acme Books * Description: Registers the book CPT and a related block. * Version: 1.0.0 * Requires PHP: 8.4 * Requires at least: 6.9 */ defined( 'ABSPATH' ) || exit; // never expose a direct hit ``` Hooks split two ways: **actions** fire at a point in execution (`add_action('init', …)`); **filters** transform a value and must `return` it (`add_filter('the_content', …)`). Confusing them is a top-five WP bug. Register a block from a `block.json` — never duplicate metadata in PHP: ```php add_action( 'init', function () { register_block_type( __DIR__ . '/build/related-books' ); // reads block.json } ); ``` Register a custom post type with explicit capabilities and labels: ```php add_action( 'init', function () { register_post_type( 'book', array( 'public' => true, 'show_in_rest' => true, // required for the block editor 'supports' => array( 'title', 'editor', 'thumbnail' ), 'labels' => array( 'name' => 'Books', 'singular_name' => 'Book' ), ) ); } ); ``` Every write path needs a **capability check + nonce**, and every output/query needs escaping/sanitizing. This is the line between a plugin and a vulnerability. ```php // Bad — SQL injection, no auth $rows = $wpdb->get_results( "SELECT * FROM {$wpdb->posts} WHERE post_author = $id" ); // Good — capability, nonce, prepared statement if ( ! current_user_can( 'edit_posts' ) ) { wp_die( 'nope' ); } check_admin_referer( 'acme_save' ); $rows = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->posts} WHERE post_author = %d", $id ) ); echo esc_html( $rows[0]->post_title ); ``` Sanitize on input (`sanitize_text_field`, `absint`), escape on output (`esc_html`, `esc_attr`, `esc_url`, `wp_kses` for allowed HTML). ## Security hardening The single highest-impact habit is keeping core, plugins, and themes updated — 2024 saw 7,966 new ecosystem vulnerabilities, +34% YoY, and the vast majority hit known-vulnerable extensions. Baseline `wp-config.php` constants: ```php define( 'DISALLOW_FILE_EDIT', true ); // kills dashboard Theme/Plugin editor; SFTP/Git unaffected define( 'WP_AUTO_UPDATE_CORE', 'minor' ); define( 'FORCE_SSL_ADMIN', true ); ``` Use **Application Passwords** (WP 5.6+) for REST/API machine auth — individually revocable, cannot log into `wp-login.php`, and the right answer when a script or [nextjs](../nextjs/SKILL.md) front end needs to talk to WP. Never reuse the admin password in a script. For the full block — file-permission matrix (dirs 755 / files 644 / wp-config 600), `DISALLOW_FILE_MODS`, nginx/.htaccess security headers, login lockdown, XML-RPC and user-enumeration disabling, version-disclosure removal — see [references/hardening.md](references/hardening.md). Generic OWASP/threat-modeling not tied to the WP attack surface is [secure-coding](../secure-coding/SKILL.md). ## Performance Two caches, different jobs: an **object cache** (Redis/Memcached via a drop-in) memoizes DB query results across requests; a **page cache** stores whole rendered HTML pages. You usually want both. Then: - **Audit autoloaded options** first when wp-admin crawls — a few MB of autoloaded junk loads on *every* request. Find offenders with the SQL in the reference. - Enqueue assets per block (above); defer/async non-critical scripts. - Speculative loading (prerender/prefetch on hover) ships in 6.8+; tune it rather than bolting on a plugin. Full Redis wiring, the autoload audit query, transients, and a WP-tied Core Web Vitals checklist are in [references/performance.md](references/performance.md). Generic CWV/load-testing methodology divorced from WordPress is the [performance](../performance/SKILL.md) sibling. ## WooCommerce **HPOS** (High-Performance Order Storage) is the default order datastore for new installs since WooCommerce 8.2 — orders live in dedicated tables, not `wp_posts`. Enable/migrate and verify with WP-CLI: ```bash wp wc hpos enable # turn on custom order tables wp wc cot sync # backfill/sync existing orders wp wc cot verify_cot_data # confirm parity before flipping authority ``` Any plugin that touches orders **must declare HPOS compatibility**, or WooCommerce disables it in HPOS mode: ```php add_action( 'before_woocommerce_init', function () { if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) { \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true ); } } ); ``` Store/checkout/product setup checklist and migration caveats: [references/woocommerce.md](references/woocommerce.md). A Shopify store is the [shopify](../shopify/SKILL.md) sibling. ## WP-CLI & local dev `wp` is the operational backbone — scriptable, faster than the dashboard, and safe on serialized data. - **Local stack:** `wp-env start` (Dockerized WP). Scaffold a block/plugin with `npx @wordpress/create-block acme-block`. - **Migrations:** `wp search-replace` is serialization-safe — never run a raw SQL `REPLACE` on the DB, it corrupts serialized arrays. Dry-run first: ```bash wp search-replace 'https://staging.example.com' 'https://example.com' --all-tables --dry-run wp db export backup.sql # always export before a real run wp search-replace 'https://staging.example.com' 'https://example.com' --all-tables ``` - **Cron:** WP's pseudo-cron only fires on traffic. For reliable schedules, define `DISABLE_WP_CRON` true and run `wp cron event run --due-now` from real system cron. ## Anti-patterns | Anti-pattern | Why it's wrong | Do instead | | --- | --- | --- | | App logic in `functions.php` | Dies with the theme; not portable | Standalone plugin or mu-plugin | | Editing a parent theme / core files | Wiped on update | Child theme; hooks/filters | | `query_posts()` | Breaks the main query, no pagination | `WP_Query` or `pre_get_posts` | | `$wpdb->query("… $var …")` | SQL injection | `$wpdb->prepare()` with `%d`/`%s` | | `<script src>`/`<link>` in templates | Not cached, no dependency graph | `wp_enqueue_script/style`, `wp_enqueue_block_style` | | Secrets pasted in dashboard file editor | Logged, world-readable, version-control blind | `wp-config.php` constants + `DISALLOW_FILE_EDIT` | | Page builder for structural layout | Bloat, lock-in, broken CWV | Block theme + patterns | | Disabling auto-updates, never patching | 7,966 vulns/yr land on stale plugins | `WP_AUTO_UPDATE_CORE`; `wp plugin update --all` | | Raw SQL `REPLACE` to change URLs | Corrupts serialized data | `wp search-replace` | | Order-touching plugin without HPOS declaration | WooCommerce disables it | `FeaturesUtil::declare_compatibility` | ## verify.sh `scripts/verify.sh <path>` statically scans theme/plugin/config code for these anti-patterns — committed DB creds or `AUTH_KEY`/salt literals, missing `DISALLOW_FILE_EDIT` when a `wp-config.php` is in scope, `eval(`/`base64_decode(`, `query_posts(`, unprepared `$wpdb` interpolation, and hardcoded `<script src=`/`<link rel="stylesheet">` in PHP templates. Read-only; exits 0 on a clean or empty target, non-zero on any FAIL so it can gate CI.
Voir sur GitHub