This file is the single source of truth for project standards, coding conventions, and development workflows in this repository. All contributors — human or automated — should follow these rules.
Tool-specific configuration lives in dedicated locations:
- GitHub Copilot:
.github/copilot-instructions.mdand.github/instructions/*.instructions.md - Cursor:
.cursor/rules/*.mdc - Claude:
claude.md
Code Snippets is a WordPress plugin that lets site owners manage and execute PHP, HTML, CSS, and JavaScript code snippets through a graphical interface — replacing the need to edit functions.php or maintain multiple single-purpose plugins.
<root>/
├── src/ # Shipped plugin root
│ ├── code-snippets.php # Plugin bootstrap
│ ├── php/ # PHP application code (PSR-4: Code_Snippets\)
│ │ ├── Plugin.php # Main orchestrator
│ │ ├── Admin/ # Admin UI, menus
│ │ ├── Core/ # Bootstrap, safe mode
│ │ ├── REST_API/ # REST endpoint controllers
│ │ ├── Model/ # Snippet data model
│ │ ├── Flat_Files/ # File-based snippet storage
│ │ ├── Integration/ # Third-party integrations
│ │ ├── Migration/ # Data migration logic
│ │ ├── Settings/ # Plugin settings
│ │ └── Utils/ # Shared utilities
│ ├── js/ # TypeScript / React source
│ │ ├── entries/ # Webpack entrypoints
│ │ ├── components/ # Feature-grouped React UI
│ │ ├── hooks/ # Custom React hooks
│ │ ├── services/ # API service layer
│ │ ├── types/ # TypeScript type definitions
│ │ └── utils/ # JS utilities
│ ├── css/ # SCSS source files
│ ├── dist/ # Webpack output (built assets, not committed)
│ ├── vendor/ # Composer dependencies
│ └── composer.json # PHP dependency management
├── config/ # Webpack and PostCSS configuration
├── scripts/ # Release, versioning, and linter scripts
├── tests/ # PHPUnit suites, Playwright E2E specs
├── assets/ # WordPress.org screenshots, icons, and banners
└── .github/ # CI workflows, issue templates, Copilot instructions
| Layer | Technology |
|---|---|
| Backend | PHP 7.4+, WordPress APIs, PSR-4 via Composer |
| Frontend | TypeScript, React 18, @wordpress/components, CodeMirror 5 |
| Styling | SCSS (PostCSS, logical properties via stylelint-use-logical) |
| Build | Webpack 5, Babel, ts-loader, sass-loader |
| PHP linting | PHPCS + WPCS (npm run lint:php) |
| JS/TS linting | ESLint 9 flat config (npm run lint:js) |
| CSS linting | Stylelint (npm run lint:styles) |
| PHP tests | PHPUnit (npm run test:php) |
| E2E tests | Playwright (npm run test:playwright) |
| WP dev env | @wordpress/env / wp-env (npm run wp-env:start) |
| Pre-commit | Husky + lint-staged (auto-fix on commit) |
| PHP deps | Composer with Imposter (namespace-prefixing) |
- Follow the WordPress Coding Standards for PHP, JS, CSS, and HTML.
strict_types=1is not enforced project-wide — match the style of the file being edited.- Keep lines under 120 characters for PHP; 100 for JS/TS.
- All user-visible strings must be wrapped in a WordPress i18n function with the text domain
code-snippets. - Use
__(),_e(),esc_html__(),esc_attr__(),_x(),_n()as appropriate — never echo raw translatable strings. - Do not load translations before
initorplugins_loaded.
- Namespace:
Code_Snippets\— all new classes must live under this namespace and be PSR-4 autoloaded. - Vendor dependencies: always use the prefixed namespace
Code_Snippets\Vendor\…(Imposter-prefixed). - Guard direct execution at the top of every standalone file:
defined('ABSPATH') || exit; - Use
wp_die()for fatal admin errors; neverdie()orexitwith user-facing output. - In
src/php/Plugin.php(and Core bootstrap), rely onautoload.php; avoid manualrequire_oncechains. - Avoid creating custom database tables. Prefer WordPress-native storage:
wp_optionsfor settings/flags, transients for cached/temporary data, or hidden custom post types for structured content. Custom tables require manual schema management, migration, and uninstall logic — only justify them when native storage genuinely cannot meet the requirement.
- Export types that appear in exported function signatures — do not leak unexported shapes.
- Use
@wordpress/api-fetchor the service layer insrc/js/services/for all WP REST calls. - Prefer
@wordpress/componentsfor UI; avoid reimplementing existing WP admin patterns.
- Use logical CSS properties (e.g.,
margin-inline-startnotmargin-left) — enforced by stylelint.
- PSR-4 autoloading via Composer — class files are discovered automatically; do not
requirethem manually. - Imposter prefixing — all
vendor/code is rewritten toCode_Snippets\Vendor\…to prevent conflicts with other plugins using the same libraries. - Snippet model — core data unit is
Code_Snippets\Model\Snippet; use its API for reading/writing snippet data, not raw DB access. - Hook-driven extensibility — use WordPress filters and actions as the primary extension mechanism; expose a filter before changing any default behaviour that may be preference-driven.
- Safe mode —
src/php/Core/load.phpboots a recovery path when safe mode is active; any change to snippet execution must preserve this path.
- Production branch:
core - Pre-release branch:
core-beta - Development branches:
feat/…,fix/…,chore/…,hotfix/… - Branch from
core-betafor all feature and fix work. - Open PRs back into
core-beta. - Use merge commits (not squash/rebase) when merging dev branches into
core-beta. - Hotfixes branch from
coreand merge directly back intocore.
# Install dependencies
npm install # Node deps + Husky hooks
cd src && composer install # PHP deps (or: npm run bundle)
# WordPress environment
npm run wp-env:start # Start local WP instance
npm run wp-env:stop
npm run wp-env:clean # Reset all data
# Build
npm run build # Webpack build (JS + CSS → src/dist/)
npm run watch # Webpack watch mode
npm run bundle # Full distribution build → bundle/
# Lint
npm run lint # All: PHP + JS + CSS
npm run lint:php # PHPCS with WPCS
npm run lint:js # ESLint
npm run lint:styles # Stylelint
# Tests
npm run test:php # PHPUnit
npm run test:playwright # Playwright E2E (requires wp-env running)
./test-playwright.sh # Helper script for PlaywrightApply to every change:
- Sanitize all user inputs server-side before use.
- Escape all outputs at the correct boundary (HTML, attribute, JS, URL).
- Verify a WordPress nonce on every state-changing request.
- Verify
current_user_can()alongside nonce checks. - Never use
eval,create_function, orcall_user_funcwith untrusted input. - Apply
rel="noopener noreferrer"to everytarget="_blank"link. - Use
$wpdb->prepare()for every dynamic SQL value. - Any feature fetching remote content must document its trust model.
- Unit tests (PHPUnit) — required for all PHP logic changes.
- Integration tests (PHPUnit) — required when changing DB schema, REST endpoints, or hook behaviour.
- E2E tests (Playwright) — required for changes affecting snippet create/edit/execute flows.
- Minimum requirements - Tests must be compatible with the minimum supported PHP 7.4 and WordPress 5.5.
- Build - Generated build artifacts (
src/dist/, Composer autoload maps) must be regenerated when source changes.
- Do not create custom database tables without strong justification — use
wp_options, transients, or custom post types instead. - Do not echo raw user input — always escape at output.
- Do not concatenate translated string fragments — translate full sentences.
- Do not place HTML markup inside translated strings.
- Do not rely on "deactivate the plugin" as a recovery path — safe mode must remain functional.
- Do not ship build artifacts to feature branches —
src/dist/andbundle/are built in CI.