Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
211 changes: 211 additions & 0 deletions .github/instructions/plugin-structure.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
---
description: "WordPress block plugin structure conventions for all LightSpeed plugins: directory layout, block.json, asset enqueueing, security, and i18n."
applyTo: "**"
file_type: "instructions"
version: "v1.0"
last_updated: "2026-05-20"
owners: ["LightSpeed Team"]
tags: ["wordpress", "plugin", "blocks", "block-json", "structure", "php", "i18n"]
domain: "plugin-hardening"
stability: "stable"
---

# WordPress Block Plugin Structure

You are a WordPress block plugin architect. Follow our block-first plugin conventions to scaffold, structure, and maintain LightSpeed plugins. Avoid page-builder patterns, direct SQL, and enqueuing assets globally where block-scoped loading suffices.

## Overview

Applies to all LightSpeed WordPress plugins that ship one or more Gutenberg blocks. Covers directory layout, `block.json` conventions, asset enqueueing, PHP organisation, security, and i18n. Excludes theme-only patterns—see the block theme guidance for those.

## General Rules

- Scaffold new blocks with `@wordpress/create-block`; align the output to the conventions below.
- Use `block.json` as the canonical source of block metadata, attributes, and supported features.
- Separate editor assets from front-end assets; never enqueue editor-only code on the front end.
- Register all blocks via `register_block_type()` pointing to the `block.json` file—avoid manual registration of attributes and scripts.
- Follow [WordPress Coding Standards](https://developer.wordpress.org/coding-standards/) for PHP, JS, CSS, and HTML.
- Apply `sanitize_*`, `esc_*`, and `wp_kses_post()` at all input and output boundaries.
- Use a plugin-specific text domain and run `wp-scripts i18n make-pot` as part of the build.

## Detailed Guidance

### Directory Layout

Prefer this layout for a single-block plugin; extend it for multi-block plugins by repeating the `src/<block-name>/` pattern.

```text
my-plugin/
├── my-plugin.php # Plugin header, bootstrap loader
├── readme.txt # WordPress.org readme
├── package.json # wp-scripts, node tooling
├── composer.json # PHP tooling (PHPCS, PHPStan)
├── block.json # Root block metadata (single-block plugins only)
├── src/
│ ├── block.json # Preferred: block metadata lives with source
│ ├── edit.js # Editor component
│ ├── save.js # Front-end render (or null for dynamic blocks)
│ ├── index.js # Block registration entry point
│ ├── editor.scss # Editor-only styles
│ └── style.scss # Shared/front-end styles
├── build/ # wp-scripts output (gitignored)
├── includes/
│ ├── class-my-plugin.php # Main plugin class
│ └── functions.php # Utility functions
└── languages/
└── my-plugin.pot # Generated POT file
```

For multi-block plugins, place each block under its own subfolder:

```text
src/
├── my-block/
│ ├── block.json
│ ├── edit.js
│ ├── save.js
│ ├── index.js
│ ├── editor.scss
│ └── style.scss
└── another-block/
└── ...
```

### Plugin File Header

The main PHP file must include the standard WordPress plugin header:

```php
<?php
/**
* Plugin Name: My LightSpeed Plugin
* Plugin URI: https://lightspeedwp.agency/
* Description: A block-first WordPress plugin.
* Version: 1.0.0
* Requires at least: 6.4
* Requires PHP: 8.0
* Author: LightSpeed
* Author URI: https://lightspeedwp.agency/
* License: GPL-2.0-or-later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: my-plugin
* Domain Path: /languages
*/

if ( ! defined( 'ABSPATH' ) ) {
exit;
}
```

### `block.json` Conventions

- Always include `$schema` pointing to the WordPress block schema for IDE support and validation.
- Set `"apiVersion": 3` unless you explicitly need an older API.
- Declare all supported features under `"supports"` rather than enabling them manually.
- Use `"editorScript"` and `"style"` (or `"editorStyle"`) to reference build artefacts; let `register_block_type()` handle enqueueing automatically.

```json
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "my-plugin/my-block",
"version": "1.0.0",
"title": "My Block",
"category": "widgets",
"description": "A short description of the block.",
"textdomain": "my-plugin",
"editorScript": "file:./index.js",
"editorStyle": "file:./index.css",
"style": "file:./style-index.css",
"supports": {
"html": false,
"color": { "background": true, "text": true },
"spacing": { "margin": true, "padding": true },
"typography": { "fontSize": true }
},
"attributes": {
"content": {
"type": "string",
"default": ""
}
}
}
```

### Asset Enqueueing

- Prefer automatic asset loading via `register_block_type( __DIR__ . '/build/block-name/block.json' )`.
- Only use `wp_enqueue_scripts` / `enqueue_block_editor_assets` for assets that cannot be declared in `block.json`.
- Never enqueue editor JS on the front end; never enqueue front-end-only assets in the editor.

```php
// Preferred: automatic loading via block.json
add_action( 'init', function() {
register_block_type( __DIR__ . '/build/block-name' );
} );
```

### Security

- Validate all user input with `sanitize_text_field()`, `absint()`, `sanitize_url()`, or appropriate sanitizers.
- Escape all output: `esc_html()`, `esc_attr()`, `esc_url()`, `wp_kses_post()`.
- Use nonces for any form submission or AJAX request that modifies data.
- Never trust client-side attribute values in dynamic block `render_callback`—re-validate server-side.
- Use `current_user_can()` before privileged operations.

```php
// Good: validate, then escape on output
$title = sanitize_text_field( $attributes['title'] ?? '' );
echo '<h2>' . esc_html( $title ) . '</h2>';
```

### i18n

- Declare the text domain in both the plugin header and `block.json` (`"textdomain"` key).
- Wrap all user-facing strings in `__()`, `esc_html__()`, or `_n()` with the plugin text domain.
- In JavaScript, import `{ __ }` from `@wordpress/i18n`.
- Generate the POT file: `wp i18n make-pot . languages/my-plugin.pot --domain=my-plugin`.
- Add `wp-scripts i18n make-json languages/ --no-purge` to the build pipeline to create JSON translation files.

### PHP Class Organisation

- Use a main plugin class to namespace all hooks and methods.
- Register hooks in an `init()` or `run()` method, not in the constructor.
- Keep the constructor lean: set version constants and properties only.

```php
class My_Plugin {
public function __construct( string $version ) {
$this->version = $version;
}

public function run(): void {
add_action( 'init', [ $this, 'register_blocks' ] );
}

public function register_blocks(): void {
register_block_type( __DIR__ . '/../build/my-block' );
}
}
```

## Examples

- **Good:** `register_block_type( __DIR__ . '/build/my-block' )` with a matching `block.json`; editor styles in `editorStyle`, shared styles in `style`; all output wrapped in `esc_html()`.
- **Avoid:** Manually registering block scripts with `wp_register_script` and duplicating metadata already declared in `block.json`; enqueuing editor assets unconditionally via `wp_enqueue_scripts`.

## Validation

- Run `npm run build` to confirm `@wordpress/scripts` compiles without errors.
- Run `composer phpcs` (PHPCS with WPCS) on the `includes/` and plugin root PHP.
- Check `block.json` validates against the schema: `npx @wordpress/scripts check-engines`.
- Confirm no editor styles leak to the front end by inspecting network requests on a published post.

## References

- [coding-standards.instructions.md](./coding-standards.instructions.md)
- [a11y.instructions.md](./a11y.instructions.md)
- [WordPress Block Editor Handbook](https://developer.wordpress.org/block-editor/)
- [block.json schema reference](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/)
- [@wordpress/create-block](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-create-block/)
- [WordPress Plugin Handbook](https://developer.wordpress.org/plugins/)
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ Start here for all key standards:
| ------------------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------ |
| **Instructions Guide** | [.github/instructions/instructions.instructions.md](.github/instructions/instructions.instructions.md) | Guide for authoring and maintaining instruction files |
| **Custom Instructions** | [.github/custom-instructions.md](.github/custom-instructions.md) | Repo-local Copilot instructions and `.github` boundary rules |
| **Claude Instructions** | [CLAUDE.md](CLAUDE.md) | Claude-specific project instructions; companion to this file |
| **Main Agent Index** | [.github/agents/agent.md](.github/agents/agent.md) | Directory of agent specs, stubs, usage, implementation |
| **Prompts Index** | [.github/prompts/prompts.md](.github/prompts/prompts.md) | Legacy prompt index pending skills/cookbook migration |
| **Instruction Migration** | [.github/MIGRATION_GUIDE.md](.github/MIGRATION_GUIDE.md) | Mapping from legacy instruction files to the 5 consolidated guides |
Expand Down
97 changes: 97 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
---
title: "LightSpeed .github — Claude Instructions"
description: "Claude-specific project instructions for the LightSpeed .github repository."
version: "v1.0"
last_updated: "2026-05-20"
file_type: "agents-index"
maintainer: "LightSpeed Team"
---

# CLAUDE.md — LightSpeed .github

> Full organisation-wide AI rules, coding standards, and contribution guidelines live in [AGENTS.md](./AGENTS.md). Read that file first.

## What This Repository Is

This is the **LightSpeed organisation `.github` control plane**. It owns:

- GitHub community-health files (issue templates, PR templates, discussion templates, saved replies, code of conduct, security policy).
- Organisation-wide labels, labeler rules, and issue types.
- GitHub Actions workflows for labeling, metrics, releases, and validation.
- Repo-local Copilot and agent instructions (`.github/instructions/`, `.github/custom-instructions.md`).
- Reports, project artefacts, and active planning documents.

It also hosts **portable AI operations assets** in top-level source folders that are intended to be reusable outside this repository:

| Folder | Purpose |
| --- | --- |
| `agents/` | Portable agent specifications |
| `cookbook/` | Recipes, playbooks, and implementation guides |
| `hooks/` | Portable hooks and guardrails |
| `instructions/` | Portable instruction files (no `.github` assumptions) |
| `plugins/` | Installable plugin bundles |
| `skills/` | Self-contained skills with `SKILL.md` entrypoints |
| `workflows/` | Portable agentic workflows |

Do **not** place reusable assets under `.github/`—use the matching top-level folder instead.

## Development Commands

```bash
# Install dependencies
npm ci

# Run all tests
npm test

# Lint Markdown files
npm run lint:md

# Lint JS/TS files
npm run lint:js

# Format files
npm run format

# Validate frontmatter
npm run validate:frontmatter
```

## Key Conventions

- **Language:** UK English throughout (optimise, organisation, colour, behaviour).
- **Coding Standards:** Follow [WordPress Coding Standards](https://developer.wordpress.org/coding-standards/) for PHP, plus ESLint/Prettier for JS/TS and PHPCS/WPCS for PHP.
- **Security:** Validate all input, escape all output, use nonces, never commit secrets.
- **Accessibility:** WCAG 2.2 AA minimum; semantic HTML, keyboard support, sufficient contrast.
- **Performance:** Avoid unnecessary JS, defer/lazy-load where possible, prefer native blocks.
- **No `references` frontmatter field:** Use inline links or footer sections instead.
- **Instruction files:** Follow the pattern in `.github/instructions/instructions.instructions.md`—frontmatter + role declaration + Overview + General Rules + Detailed Guidance + Examples + Validation + References.

## Repository Boundaries

| Asset Type | Belongs In |
| --- | --- |
| GitHub-native governance (templates, labels, workflows) | `.github/` |
| Repo-local Copilot/agent instructions | `.github/instructions/` or `.github/custom-instructions.md` |
| Reports, audits, metrics | `.github/reports/{category}/` |
| Active project artefacts | `.github/projects/active/{slug}/` |
| Temporary scratch files | `.github/tmp/` (clean up before PR) |
| Portable reusable AI assets | top-level source folders above |
| Permanent human documentation | `docs/` |

## What Not to Do

- Do not add WordPress plugin or theme project-specific code to `.github/`.
- Do not place reports or task trackers in `docs/` or the repo root.
- Do not create instruction files with a `references` frontmatter field.
- Do not move existing agents, instructions, or schemas without a migration issue that records source path, target path, and validation plan.
- Do not enqueue editor-only WordPress assets on the front end (and vice versa).
- Do not commit `node_modules/`, `build/`, or other generated artefacts.

## Related Files

- [AGENTS.md](./AGENTS.md) — full global AI rules
- [.github/custom-instructions.md](./.github/custom-instructions.md) — Copilot-specific repo instructions
- [.github/instructions/coding-standards.instructions.md](./.github/instructions/coding-standards.instructions.md) — unified coding standards
- [.github/instructions/file-organisation.instructions.md](./.github/instructions/file-organisation.instructions.md) — canonical file placement rules
- [.github/instructions/plugin-structure.instructions.md](./.github/instructions/plugin-structure.instructions.md) — WordPress block plugin structure
15 changes: 0 additions & 15 deletions Copilot-Processing.md

This file was deleted.