Skill: WordPress Plugin Standard (WP.org Compliant)
This skill guides the creation of a high-quality, secure, and WordPress.org compliant plugin. It focuses on adherence to the Plugin Check (PCP) requirements and provides a robust structure including admin interfaces.
Purpose
Standardize WordPress plugin development to ensure acceptance into the official repository, maximize security, and promote maintainability through strict separation of concerns.
Required Variables
{{plugin_name}}: Human-readable name (e.g., My Awesome Plugin).
{{plugin_slug}}: Unique slug (e.g., my-awesome-plugin).
{{namespace}}: PHP Namespace (e.g., PolyXGO\MyPlugin).
{{prefix}}: Unique prefix for functions/variables (e.g., pxmp_).
{{text_domain}}: I18n text domain (usually same as plugin slug).
Core Requirements (WordPress.org & PCP)
1. Security & Protection
- Direct Access: Use
if ( ! defined( 'ABSPATH' ) ) exit; at the top of every PHP file.
- Nonces: Verify nonces for all form submissions and AJAX requests.
- Validation & Sanitization: Sanitize all inputs (
sanitize_text_field, absint, etc.) and validate data before processing.
- Escaping: Escape all outputs strictly based on context (
esc_html, esc_attr, wp_kses, etc.).
- Capabilities: Explicitly check user capabilities (
current_user_can) for all admin actions.
2. Code Organization & Standards
- Naming: Use the
{{prefix}} for all global functions, variables, and constants.
- Namespace: Use PSR-4 namespacing (
{{namespace}}) to avoid class collisions.
- Separation of Concerns: Keep CSS and JS in separate files. AVOID inline styles or scripts unless dynamically generated values are required (use
wp_localize_script or wp_add_inline_style only when necessary).
- No Prohibited Constructs: Never use
eval(), base64_decode() for obfuscation, or short tags (<?).
3. Required Components
- Main Plugin File: Must contain the required header comment.
readme.txt: Standard WordPress.org format.
- Admin Interface:
- A top-level or sub-menu item for the Dashboard.
- A dedicated Settings page for configuration.
- Uninstallation: Provide an
uninstall.php file to clean up data (options, tables) when the plugin is deleted.
Implementation Steps
Step 1: Initialize Main Structure
- Create the main plugin file
{{plugin_slug}}.php with the correct header.
- Initialize the main class with a singleton or static instance.
- Hook into
plugins_loaded to start the plugin logic.
Step 2: Register Admin Menu
- Hook into
admin_menu.
- Add a menu page and a sub-page for Settings.
- Enqueue admin-specific assets (CSS/JS) only on plugin pages.
Step 3: Integrate UI/UX Skill
When designing the Dashboard or Settings page:
- Call Skill: Use
(skill: ui-ux) to define the design language.
- Apply Styles: Use the colors, typography, and spacing defined by the
ui-ux skill result.
- Write styles in
assets/admin.css.
Step 4: Handle Data Persistence
- Use the Options API (
get_option, update_option) for settings.
- Ensure all data saved to the database is sanitized.
- Ensure all data retrieved from the database is escaped on output.
Standards and Rules
The Prefixing Rule
Every global identifier MUST start with {{prefix}}.
- ✅
{{prefix}}get_settings()
- ❌
get_settings()
The "No Inline" Rule
- CSS must be in
assets/css/admin.css.
- JS must be in
assets/js/admin.js.
- Use
wp_enqueue_style and wp_enqueue_script correctly.
The "Smart Flush" Rule (Friendly URLs)
If the plugin uses custom post types or custom permalink structures, you MUST implement a "Queue & Flush" mechanism to update rewrite rules automatically. NEVER call flush_rewrite_rules() on every page load or init hook directly without a condition.
Implementation Pattern:
- Queue Flush: When settings verify (e.g., via
update_option hook), set a temporary flag.add_action('update_option_{{prefix}}permalink_settings', function($old, $new) {
update_option('{{prefix}}flush_rewrite_flag', true);
}, 10, 2);
- Execute Flush: On the next
admin_init, check and flush.add_action('admin_init', function() {
if (get_option('{{prefix}}flush_rewrite_flag')) {
flush_rewrite_rules();
delete_option('{{prefix}}flush_rewrite_flag');
}
});
Templates
- plugin-main.php
- admin-dashboard.php
- admin-settings.php
- readme.txt
- uninstall.php
- assets/admin-css.css
- assets/admin-js.js
1---2name: plugin-standard3description: Skill: WordPress Plugin Standard (WP.org Compliant)4---5# Skill: WordPress Plugin Standard (WP.org Compliant)67This skill guides the creation of a high-quality, secure, and WordPress.org compliant plugin. It focuses on adherence to the Plugin Check (PCP) requirements and provides a robust structure including admin interfaces.89## Purpose10Standardize WordPress plugin development to ensure acceptance into the official repository, maximize security, and promote maintainability through strict separation of concerns.1112## Required Variables13- `{{plugin_name}}`: Human-readable name (e.g., My Awesome Plugin).14- `{{plugin_slug}}`: Unique slug (e.g., my-awesome-plugin).15- `{{namespace}}`: PHP Namespace (e.g., PolyXGO\MyPlugin).16- `{{prefix}}`: Unique prefix for functions/variables (e.g., pxmp_).17- `{{text_domain}}`: I18n text domain (usually same as plugin slug).1819## Core Requirements (WordPress.org & PCP)2021### 1. Security & Protection22- **Direct Access**: Use `if ( ! defined( 'ABSPATH' ) ) exit;` at the top of every PHP file.23- **Nonces**: Verify nonces for all form submissions and AJAX requests.24- **Validation & Sanitization**: Sanitize all inputs (`sanitize_text_field`, `absint`, etc.) and validate data before processing.25- **Escaping**: Escape all outputs strictly based on context (`esc_html`, `esc_attr`, `wp_kses`, etc.).26- **Capabilities**: Explicitly check user capabilities (`current_user_can`) for all admin actions.2728### 2. Code Organization & Standards29- **Naming**: Use the `{{prefix}}` for all global functions, variables, and constants.30- **Namespace**: Use PSR-4 namespacing (`{{namespace}}`) to avoid class collisions.31- **Separation of Concerns**: Keep CSS and JS in separate files. AVOID inline styles or scripts unless dynamically generated values are required (use `wp_localize_script` or `wp_add_inline_style` only when necessary).32- **No Prohibited Constructs**: Never use `eval()`, `base64_decode()` for obfuscation, or short tags (`<?`).3334### 3. Required Components35- **Main Plugin File**: Must contain the required header comment.36- **`readme.txt`**: Standard WordPress.org format.37- **Admin Interface**:38 - A top-level or sub-menu item for the **Dashboard**.39 - A dedicated **Settings** page for configuration.40- **Uninstallation**: Provide an `uninstall.php` file to clean up data (options, tables) when the plugin is deleted.4142## Implementation Steps4344### Step 1: Initialize Main Structure451. Create the main plugin file `{{plugin_slug}}.php` with the correct header.462. Initialize the main class with a singleton or static instance.473. Hook into `plugins_loaded` to start the plugin logic.4849### Step 2: Register Admin Menu501. Hook into `admin_menu`.512. Add a menu page and a sub-page for Settings.523. Enqueue admin-specific assets (CSS/JS) only on plugin pages.5354### Step 3: Integrate UI/UX Skill55When designing the Dashboard or Settings page:561. **Call Skill**: Use `(skill: ui-ux)` to define the design language.572. **Apply Styles**: Use the colors, typography, and spacing defined by the `ui-ux` skill result.583. Write styles in `assets/admin.css`.5960### Step 4: Handle Data Persistence611. Use the Options API (`get_option`, `update_option`) for settings.622. Ensure all data saved to the database is sanitized.633. Ensure all data retrieved from the database is escaped on output.6465## Standards and Rules6667### The Prefixing Rule68Every global identifier MUST start with `{{prefix}}`.69- ✅ `{{prefix}}get_settings()`70- ❌ `get_settings()`7172### The "No Inline" Rule73- CSS must be in `assets/css/admin.css`.74- JS must be in `assets/js/admin.js`.75- Use `wp_enqueue_style` and `wp_enqueue_script` correctly.7677### The "Smart Flush" Rule (Friendly URLs)78If the plugin uses custom post types or custom permalink structures, you MUST implement a "Queue & Flush" mechanism to update rewrite rules automatically. **NEVER** call `flush_rewrite_rules()` on every page load or `init` hook directly without a condition.7980**Implementation Pattern:**811. **Queue Flush**: When settings verify (e.g., via `update_option` hook), set a temporary flag.82 ```php83 add_action('update_option_{{prefix}}permalink_settings', function($old, $new) {84 update_option('{{prefix}}flush_rewrite_flag', true);85 }, 10, 2);86 ```872. **Execute Flush**: On the next `admin_init`, check and flush.88 ```php89 add_action('admin_init', function() {90 if (get_option('{{prefix}}flush_rewrite_flag')) {91 flush_rewrite_rules();92 delete_option('{{prefix}}flush_rewrite_flag');93 }94 });95 ```9697## Templates98- [plugin-main.php](templates/plugin-main.php)99- [admin-dashboard.php](templates/admin-dashboard.php)100- [admin-settings.php](templates/admin-settings.php)101- [readme.txt](templates/readme.txt)102- [uninstall.php](templates/uninstall.php)103- [assets/admin-css.css](templates/assets/admin-css.css)104- [assets/admin-js.js](templates/assets/admin-js.js)