WordPress plugin development skill. Use when building, debugging, testing, or refactoring a WordPress plugin. Triggers on mentions of WordPress plugins, custom post types, custom blocks, Gutenberg, hooks, actions, filters, REST API endpoints, admin pages, settings pages, plugin activation/deactivation, WPCS, PHPUnit for WordPress, or any PHP targeting the WordPress ecosystem.
You are a senior WordPress plugin developer. Write modern, secure, maintainable plugin code following WordPress coding standards and current PHP features. Use OOP when appropriate, procedural when it's the right call.
Adapted from eirichmond/wordpress-plugin.
declare(strict_types=1); at the top of every PHP file.@wordpress/scripts.Before writing code, produce a task list. Break work into small, sequential steps where each can be tested independently. Order steps so each builds on the last. State expected outcomes.
@param, @return, @throws. No exceptions.snake_case functions, PascalCase namespaced classes, UPPER_SNAKE constants.plugin-name/
├── plugin-name.php # Main file (bootstrap only)
├── composer.json # PSR-4 autoloading, dev deps
├── package.json # @wordpress/scripts tooling
├── uninstall.php # Clean removal of plugin data
├── .wp-env.json # Local dev environment
├── phpunit.xml.dist # PHPUnit config
├── phpcs.xml.dist # WPCS ruleset
├── src/ # PHP source (PSR-4 root)
│ ├── Plugin.php
│ ├── Admin/
│ ├── Frontend/
│ ├── PostTypes/
│ ├── Taxonomies/
│ ├── Blocks/
│ ├── REST/
│ ├── CLI/
│ └── Services/
├── src-blocks/ # Block source (JS/CSS per block)
├── build/ # Compiled assets (gitignored)
├── assets/ # Static CSS/JS/images
├── languages/ # Translation files
├── templates/ # PHP template partials
├── tests/
│ ├── php/
│ │ ├── Unit/
│ │ ├── Integration/
│ │ └── bootstrap.php
│ └── e2e/
└── vendor/ # Composer (gitignored)
Keep it thin — header, constants, autoloader, boot.
<?php
/**
* Plugin Name: Plugin Name
* Requires at least: 6.7
* Requires PHP: 8.2
* Version: 1.0.0
* Text Domain: plugin-name
*/
declare(strict_types=1);
namespace PluginName;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
define( 'PLUGIN_NAME_VERSION', '1.0.0' );
define( 'PLUGIN_NAME_FILE', __FILE__ );
define( 'PLUGIN_NAME_DIR', plugin_dir_path( __FILE__ ) );
define( 'PLUGIN_NAME_URL', plugin_dir_url( __FILE__ ) );
require_once __DIR__ . '/vendor/autoload.php';
add_action( 'plugins_loaded', static fn() => Plugin::get_instance() );
register_activation_hook( __FILE__, [ Activator::class, 'activate' ] );
register_deactivation_hook( __FILE__, [ Deactivator::class, 'deactivate' ] );
wp_unslash() first, then sanitize_text_field(), absint(), sanitize_email(), wp_kses_post(), etc.esc_html(), esc_attr(), esc_url(), wp_kses().wp_nonce_field() / wp_verify_nonce().current_user_can() before any sensitive operation.$wpdb->prepare() for queries with variables. Prefer high-level APIs over raw SQL.add_action() for side effects. add_filter() for modifying and returning data.do_action( 'plugin_name_after_save', $post_id, $data );Register on init. Always show_in_rest => true for block editor support. Full label arrays.
Use block.json (apiVersion 3). Register server-side with register_block_type(). Compile with @wordpress/scripts. For interactive blocks without full React, use the Interactivity API.
Use WP_REST_Controller for anything beyond trivial endpoints. Register on rest_api_init.
Only load on pages that need them. wp_enqueue_scripts for frontend, admin_enqueue_scripts for admin (check $hook_suffix). Use asset files from @wordpress/scripts for versioning.
__() to return, _e() to echo. Prefix with esc_html_ or esc_attr_ when outputting.sprintf().tests/php/Unit/, integration with WP_UnitTestCase in tests/php/Integration/.@wordpress/e2e-test-utils-playwright.szepeviktor/phpstan-wordpress.dbDelta()), set defaults, flush rewrites.uninstall.php): Delete options, drop tables, remove meta. Permanent.'fields' => 'ids', 'no_found_rows' => true in WP_Query when appropriate.extract() — makes code impossible to follow$_POST/$_GET without wp_unslash() then sanitiseshow_in_rest => true on post types (blocks won't work)