WordPress Development — Copilot Instructions
Goal: Generate WordPress code that is secure, performant, testable, and compliant with official WordPress practices. Prefer hooks, small functions, dependency injection (where sensible), and clear separation of concerns.
1) Core Principles
- Never modify WordPress core. Extend via actions and filters.
- For plugins, always include a header and guard direct execution in entry PHP files.
- Use unique prefixes or PHP namespaces to avoid global collisions.
- Enqueue assets; never inline raw
<script>/<style> in PHP templates.
- Make user‑facing strings translatable and load the correct text domain.
Minimal plugin header & guard
<?php
defined('ABSPATH') || exit;
/**
* Plugin Name: Awesome Feature
* Description: Example plugin scaffold.
* Version: 0.1.0
* Author: Example
* License: GPL-2.0-or-later
* Text Domain: awesome-feature
* Domain Path: /languages
*/
2) Coding Standards (PHP, JS, CSS, HTML)
- Follow WordPress Coding Standards (WPCS) and write DocBlocks for public APIs.
- PHP: Prefer strict comparisons (
===, !==) where appropriate. Be consistent with array syntax and spacing as per WPCS.
- JS: Match WordPress JS style; prefer
@wordpress/* packages for block/editor code.
- CSS: Use BEM‑like class naming when helpful; avoid over‑specific selectors.
- PHP 7.4+ compatible patterns unless the project specifies higher. Avoid using features not supported by target WP/PHP versions.
Linting setup suggestions
<!-- phpcs.xml -->
<?xml version="1.0"?>
<ruleset name="Project WPCS">
<description>WordPress Coding Standards for this project.</description>
<file>./</file>
<exclude-pattern>vendor/*</exclude-pattern>
<exclude-pattern>node_modules/*</exclude-pattern>
<rule ref="WordPress"/>
<rule ref="WordPress-Docs"/>
<rule ref="WordPress-Extra"/>
<rule ref="PHPCompatibility"/>
<config name="testVersion" value="7.4-"/>
</ruleset>
// composer.json (snippet)
{
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^1.0",
"wp-coding-standards/wpcs": "^3.0",
"phpcompatibility/php-compatibility": "^9.0"
},
"scripts": {
"lint:php": "phpcs -p",
"fix:php": "phpcbf -p"
}
}
// package.json (snippet)
{
"devDependencies": {
"@wordpress/eslint-plugin": "^x.y.z"
},
"scripts": {
"lint:js": "eslint ."
}
}
3) Security & Data Handling
- Escape on output, sanitize on input.
- Escape:
esc_html(), esc_attr(), esc_url(), wp_kses_post().
- Sanitize:
sanitize_text_field(), sanitize_email(), sanitize_key(), absint(), intval().
- Capabilities & nonces for forms, AJAX, REST:
- Add nonces with
wp_nonce_field() and verify via check_admin_referer() / wp_verify_nonce().
- Restrict mutations with
current_user_can( 'manage_options' /* or specific cap */ ).
- Database: always use
$wpdb->prepare() with placeholders; never concatenate untrusted input.
- Uploads: validate MIME/type and use
wp_handle_upload()/media_handle_upload().
4) Internationalization (i18n)
- Wrap user‑visible strings with translation functions using your text domain:
__( 'Text', 'awesome-feature' ), _x(), esc_html__().
- Load translations with
load_plugin_textdomain() or load_theme_textdomain().
- Keep a
.pot in /languages and ensure consistent domain usage.
5) Performance
- Defer heavy logic to specific hooks; avoid expensive work on
init/wp_loaded unless necessary.
- Use transients or object caching for expensive queries; plan invalidation.
- Enqueue only what you need and conditionally (front vs admin; specific screens/routes).
- Prefer paginated/parameterized queries over unbounded loops.
6) Admin UI & Settings
- Use Settings API for options pages; provide
sanitize_callback for each setting.
- For tables, follow
WP_List_Table patterns. For notices, use the admin notices API.
- Avoid direct HTML echoing for complex UIs; prefer templates or small view helpers with escaping.
7) REST API
- Register with
register_rest_route(); always set a permission_callback.
- Validate/sanitize request args via the
args schema.
- Return
WP_REST_Response or arrays/objects that map cleanly to JSON.
8) Blocks & Editor (Gutenberg)
- Use
block.json + register_block_type(); rely on @wordpress/* packages.
- Provide server render callbacks when needed (dynamic blocks).
- E2E tests should cover: insert block → edit → save → front‑end render.
9) Asset Loading
add_action('wp_enqueue_scripts', function () {
wp_enqueue_style(
'af-frontend',
plugins_url('assets/frontend.css', __FILE__),
[],
'0.1.0'
);
wp_enqueue_script(
'af-frontend',
plugins_url('assets/frontend.js', __FILE__),
[ 'wp-i18n', 'wp-element' ],
'0.1.0',
true
);
});
- Use
wp_register_style/script to register first if multiple components depend on the same assets.
- For admin screens, hook into
admin_enqueue_scripts and check screen IDs.
10) Testing
PHP Unit/Integration
- Use WordPress test suite with
PHPUnit and WP_UnitTestCase.
- Test: sanitization, capability checks, REST permissions, DB queries, hooks.
- Prefer factories (
self::factory()->post->create() etc.) to set up fixtures.
<!-- phpunit.xml.dist (minimal) -->
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="tests/bootstrap.php" colors="true">
<testsuites>
<testsuite name="Plugin Test Suite">
<directory suffix="Test.php">tests/</directory>
</testsuite>
</testsuites>
</phpunit>
// tests/bootstrap.php (minimal sketch)
<?php
$_tests_dir = getenv('WP_TESTS_DIR') ?: '/tmp/wordpress-tests-lib';
require_once $_tests_dir . '/includes/functions.php';
tests_add_filter( 'muplugins_loaded', function () {
require dirname(__DIR__) . '/awesome-feature.php';
} );
require $_tests_dir . '/includes/bootstrap.php';
E2E
- Use Playwright (or Puppeteer) for editor/front‑end flows.
- Cover basic user journeys and regressions (block insertion, settings save, front‑end render).
11) Documentation & Commits
- Keep
README.md up to date: install, usage, capabilities, hooks/filters, and test instructions.
- Use clear, imperative commit messages; reference issues/tickets and summarize impact.
12) What Copilot Must Ensure (Checklist)
- ✅ Unique prefixes/namespaces; no accidental globals.
- ✅ Nonce + capability checks for any write action (AJAX/REST/forms).
- ✅ Inputs sanitized; outputs escaped.
- ✅ User‑visible strings wrapped in i18n with correct text domain.
- ✅ Assets enqueued via APIs (no inline script/style).
- ✅ Tests added/updated for new behaviors.
- ✅ Code passes PHPCS (WPCS) and ESLint where applicable.
- ✅ Avoid direct DB concatenation; always prepare queries.
1---2name: wordpress-23description: WordPress Development — Copilot Instructions4---5# WordPress Development — Copilot Instructions67**Goal:** Generate WordPress code that is secure, performant, testable, and compliant with official WordPress practices. Prefer hooks, small functions, dependency injection (where sensible), and clear separation of concerns.89## 1) Core Principles10- Never modify WordPress core. Extend via **actions** and **filters**.11- For plugins, always include a header and guard direct execution in entry PHP files.12- Use unique prefixes or PHP namespaces to avoid global collisions.13- Enqueue assets; never inline raw `<script>`/`<style>` in PHP templates.14- Make user‑facing strings translatable and load the correct text domain.1516### Minimal plugin header & guard17```php18<?php19defined('ABSPATH') || exit;20/**21 * Plugin Name: Awesome Feature22 * Description: Example plugin scaffold.23 * Version: 0.1.024 * Author: Example25 * License: GPL-2.0-or-later26 * Text Domain: awesome-feature27 * Domain Path: /languages28 */29```3031## 2) Coding Standards (PHP, JS, CSS, HTML)32- Follow **WordPress Coding Standards (WPCS)** and write DocBlocks for public APIs.33- PHP: Prefer strict comparisons (`===`, `!==`) where appropriate. Be consistent with array syntax and spacing as per WPCS.34- JS: Match WordPress JS style; prefer `@wordpress/*` packages for block/editor code.35- CSS: Use BEM‑like class naming when helpful; avoid over‑specific selectors.36- PHP 7.4+ compatible patterns unless the project specifies higher. Avoid using features not supported by target WP/PHP versions.3738### Linting setup suggestions39```xml40<!-- phpcs.xml -->41<?xml version="1.0"?>42<ruleset name="Project WPCS">43 <description>WordPress Coding Standards for this project.</description>44 <file>./</file>45 <exclude-pattern>vendor/*</exclude-pattern>46 <exclude-pattern>node_modules/*</exclude-pattern>47 <rule ref="WordPress"/>48 <rule ref="WordPress-Docs"/>49 <rule ref="WordPress-Extra"/>50 <rule ref="PHPCompatibility"/>51 <config name="testVersion" value="7.4-"/>52</ruleset>53```5455```json56// composer.json (snippet)57{58 "require-dev": {59 "dealerdirect/phpcodesniffer-composer-installer": "^1.0",60 "wp-coding-standards/wpcs": "^3.0",61 "phpcompatibility/php-compatibility": "^9.0"62 },63 "scripts": {64 "lint:php": "phpcs -p",65 "fix:php": "phpcbf -p"66 }67}68```6970```json71// package.json (snippet)72{73 "devDependencies": {74 "@wordpress/eslint-plugin": "^x.y.z"75 },76 "scripts": {77 "lint:js": "eslint ."78 }79}80```8182## 3) Security & Data Handling83- **Escape on output, sanitize on input.**84 - Escape: `esc_html()`, `esc_attr()`, `esc_url()`, `wp_kses_post()`.85 - Sanitize: `sanitize_text_field()`, `sanitize_email()`, `sanitize_key()`, `absint()`, `intval()`.86- **Capabilities & nonces** for forms, AJAX, REST:87 - Add nonces with `wp_nonce_field()` and verify via `check_admin_referer()` / `wp_verify_nonce()`.88 - Restrict mutations with `current_user_can( 'manage_options' /* or specific cap */ )`.89- **Database:** always use `$wpdb->prepare()` with placeholders; never concatenate untrusted input.90- **Uploads:** validate MIME/type and use `wp_handle_upload()`/`media_handle_upload()`.9192## 4) Internationalization (i18n)93- Wrap user‑visible strings with translation functions using your text domain:94 - `__( 'Text', 'awesome-feature' )`, `_x()`, `esc_html__()`.95- Load translations with `load_plugin_textdomain()` or `load_theme_textdomain()`.96- Keep a `.pot` in `/languages` and ensure consistent domain usage.9798## 5) Performance99- Defer heavy logic to specific hooks; avoid expensive work on `init`/`wp_loaded` unless necessary.100- Use transients or object caching for expensive queries; plan invalidation.101- Enqueue only what you need and conditionally (front vs admin; specific screens/routes).102- Prefer paginated/parameterized queries over unbounded loops.103104## 6) Admin UI & Settings105- Use **Settings API** for options pages; provide `sanitize_callback` for each setting.106- For tables, follow `WP_List_Table` patterns. For notices, use the admin notices API.107- Avoid direct HTML echoing for complex UIs; prefer templates or small view helpers with escaping.108109## 7) REST API110- Register with `register_rest_route()`; always set a `permission_callback`.111- Validate/sanitize request args via the `args` schema.112- Return `WP_REST_Response` or arrays/objects that map cleanly to JSON.113114## 8) Blocks & Editor (Gutenberg)115- Use `block.json` + `register_block_type()`; rely on `@wordpress/*` packages.116- Provide server render callbacks when needed (dynamic blocks).117- E2E tests should cover: insert block → edit → save → front‑end render.118119## 9) Asset Loading120```php121add_action('wp_enqueue_scripts', function () {122 wp_enqueue_style(123 'af-frontend',124 plugins_url('assets/frontend.css', __FILE__),125 [],126 '0.1.0'127 );128129 wp_enqueue_script(130 'af-frontend',131 plugins_url('assets/frontend.js', __FILE__),132 [ 'wp-i18n', 'wp-element' ],133 '0.1.0',134 true135 );136});137```138- Use `wp_register_style/script` to register first if multiple components depend on the same assets.139- For admin screens, hook into `admin_enqueue_scripts` and check screen IDs.140141## 10) Testing142### PHP Unit/Integration143- Use **WordPress test suite** with `PHPUnit` and `WP_UnitTestCase`.144- Test: sanitization, capability checks, REST permissions, DB queries, hooks.145- Prefer factories (`self::factory()->post->create()` etc.) to set up fixtures.146147```xml148<!-- phpunit.xml.dist (minimal) -->149<?xml version="1.0" encoding="UTF-8"?>150<phpunit bootstrap="tests/bootstrap.php" colors="true">151 <testsuites>152 <testsuite name="Plugin Test Suite">153 <directory suffix="Test.php">tests/</directory>154 </testsuite>155 </testsuites>156</phpunit>157```158159```php160// tests/bootstrap.php (minimal sketch)161<?php162$_tests_dir = getenv('WP_TESTS_DIR') ?: '/tmp/wordpress-tests-lib';163require_once $_tests_dir . '/includes/functions.php';164tests_add_filter( 'muplugins_loaded', function () {165 require dirname(__DIR__) . '/awesome-feature.php';166} );167require $_tests_dir . '/includes/bootstrap.php';168```169### E2E170- Use Playwright (or Puppeteer) for editor/front‑end flows.171- Cover basic user journeys and regressions (block insertion, settings save, front‑end render).172173## 11) Documentation & Commits174- Keep `README.md` up to date: install, usage, capabilities, hooks/filters, and test instructions.175- Use clear, imperative commit messages; reference issues/tickets and summarize impact.176177## 12) What Copilot Must Ensure (Checklist)178- ✅ Unique prefixes/namespaces; no accidental globals. 179- ✅ Nonce + capability checks for any write action (AJAX/REST/forms). 180- ✅ Inputs sanitized; outputs escaped. 181- ✅ User‑visible strings wrapped in i18n with correct text domain. 182- ✅ Assets enqueued via APIs (no inline script/style). 183- ✅ Tests added/updated for new behaviors. 184- ✅ Code passes PHPCS (WPCS) and ESLint where applicable. 185- ✅ Avoid direct DB concatenation; always prepare queries.