This document serves as the entry point for AI agents working on the IONOS WordPress monorepo. It provides high-level project context and references to detailed coding standards.
This is a WordPress monorepo using pnpm workspaces containing plugins, must-use plugins, themes, and development tools.
/
├── packages/
│ ├── wp-plugin/ WordPress plugins
│ ├── wp-mu-plugin/ Must-use plugins
│ ├── wp-theme/ WordPress themes
│ ├── docker/ Containerized development tools
│ ├── docs/ Documentation
│ └── npm/ NPM packages
├── phpunit/ PHP unit test configuration
├── playwright/ E2E test configuration
├── scripts/ Build and automation scripts
└── docs/agent/ **AI Agent Documentation**
All coding standards are organized in /docs/agent/:
- PHP Standards - PHP 8.3+, modern syntax, templating, formatting
- JavaScript Standards - ES6+, WordPress packages, async/await
- CSS Architecture - Native CSS, BEM, modern features
- Security Standards - Input sanitization, output escaping, nonces
- PHPUnit Testing - WordPress unit tests, assertions, patterns
- E2E Testing - Playwright, WordPress E2E utils, selectors
- WordPress Integration - Hooks, APIs, admin pages, database
- Git Conventions - Commitizen format, commit messages, branching
- Changeset Workflow - Versioning, changeset files, bump types
Important: Every PHP / JS / CSS file should contain a header describing its contents.
PHP:
\prefix for WordPress functions (e.g.,\add_action()) EXCEPTcheck_admin_referer()andcheck_ajax_referer()- Heredoc-printf for HTML (avoid
<?php ?>tag switching) - Late escaping: escape at output, not before storage
- Short array syntax:
[]notarray() - No Yoda conditions:
$var === 'value'not'value' === $var(literal on right) - Named parameters for non-standard PHP functions with 3+ parameters (skip parameters with default values)
- Combine multiple
isset()checks:isset($a, $b, $c)notisset($a) && isset($b) - Modern array functions:
array_find(),array_any(),array_all()(PHP 8.4+) - Arrow functions
fn() =>for single expressions, anonymousfunction() {}for multi-line - Inline/anonymous functions if only used once, named functions when reused
- Functions over classes when possible
- See PHP Standards for details
JavaScript:
- Use
@wordpress/dom-readynotDOMContentLoaded - Use
@wordpress/api-fetchfor WordPress REST API - Use
@wordpress/i18nfor all translations - Async/await over Promise chains
- Dashboard (Essentials plugin): Use EXOS framework (
window.EXOS) for React UI components - Asset Enqueuing: Entry files (
*index.js,*index.css) bundled by wp-scripts generateindex.asset.php- alwaysrequire_oncethis file and use itsdependenciesandversionin\wp_enqueue_script()/\wp_enqueue_style() - See JavaScript Standards for details
CSS:
- Prefer EXOS CSS framework (
https://ce1.uicdn.net/exos/framework/3.0/exos.min.css) for dashboard/admin UI components - Native CSS nesting (not SCSS)
- CSS Variables (not SCSS variables)
- BEM naming:
.block__element--modifier - Mobile-first responsive design
- See CSS Architecture for details
Security (see Security Standards):
- Input: Sanitize (
\sanitize_text_field(),absint()) - Output: Escape (
\esc_html(),\esc_attr(),\esc_url()) - State changes: Verify nonce (
check_admin_referer()) - Permissions: Check capability (
\current_user_can()) - Database: Use
$wpdb->prepare()always
- PHPUnit: Extend
\WP_UnitTestCase, use Arrange-Act-Assert - Playwright: Use
@wordpress/e2e-test-utils-playwright, tag tests appropriately
- PHP: 8.3+
- WordPress: 6.6+
- Node: Latest LTS
- Package Manager: pnpm
- Namespace-based Organization - Functions in namespaces, not classes
- Hook-based Extensibility - WordPress actions and filters
- Function-first Approach - Prefer functions over classes
- Heredoc Templating - Clean HTML output without tag switching
- Late Escaping - Escape at output, not before
- Shadow DOM - Dashboard uses Shadow DOM for isolation
- EXOS Framework - Dashboard UI uses EXOS React components and CSS
- Monorepo Structure - Shared tooling and centralized standards
When implementing a new feature, bug fix, or breaking change, always create a changeset file:
- Infer the affected package, bump type, and description from the user's request
- Ask interactively only for information you cannot determine from context
- Present the full changeset content and filename for user confirmation before writing
- Write the file to
.changeset/<descriptive-name>.md— do not runchangeset add
---
'@ionos-wordpress/essentials': minor
---
add user profile export featureSee Changeset Workflow for bump type rules, package names, and examples.
# PHP unit tests
pnpm test:php
# E2E tests
pnpm test:e2e
# Linting
pnpm lint
pnpm lint-fix# Build all packages
pnpm build
# Watch mode
pnpm watch# Start WordPress environment
pnpm start
# Stop environment
pnpm stop- Indentation: 2 spaces (all languages)
- Line Length: 120 characters maximum
- Line Endings: Unix-style (LF)
- Trailing Whitespace: Remove all
- Final Newline: Always include
<?php
namespace vendor\plugin\feature;
defined('ABSPATH') || exit();
// Imports
use function vendor\plugin\_helper;
use const vendor\plugin\CONSTANT;
// Constants
const FEATURE_OPTION = 'option_name';
// Functions
function initialize(): void {
\add_action('init', __NAMESPACE__ . '\setup');
}import { __ } from '@wordpress/i18n';
import domReady from '@wordpress/dom-ready';
domReady(() => {
// Initialization
});- PHPUnit:
*Test.phpintests/phpunit/ - Playwright:
*.spec.jsintests/e2e/
- Nonce Functions: NO backslash for
check_admin_referer()andcheck_ajax_referer() - Tag Switching: Avoid
<?php ?>tag switching - use heredoc pattern - Early Escaping: Don't escape before storage - escape at output
- Option Values: Use string values (e.g.,
'enabled'/'disabled') not booleans for WordPress options to avoid type coercion issues - DOM Ready: Use
@wordpress/dom-readynot nativeDOMContentLoaded - API Fetch: Use
@wordpress/api-fetchnot rawfetch()for WordPress REST - Prepared Statements: Always use
$wpdb->prepare()for SQL - Late Binding: Functions referenced in hooks use
__NAMESPACE__ . '\function_name' - Commit Messages: Use Commitizen format with plugin scope:
feat(plugin): description - Asset Files: Always
includethe auto-generatedindex.asset.phpbefore enqueuing bundled scripts/styles - Changeset Required: Every feature/fix needs a
.changeset/*.mdfile — present it to the user for approval before writing
- Questions about standards: Reference
/docs/agent/documentation - Plugin-specific patterns: Check existing code in the same plugin
- WordPress functions: Reference WordPress Developer Resources
- Main Branch:
develop - Commit Format: Commitizen standard (Conventional Commits)
- Commit Scope: Include plugin/feature name for plugin changes (e.g.,
feat(essentials): description) - Pull Requests: Reference related issues, provide clear description
See Git Conventions for detailed commit message format and examples.
When starting work on this repository:
- Read relevant standards in
/docs/agent/ - Review existing code in the feature area you'll modify
- Run tests to ensure environment is working
- Follow patterns established in the codebase
For detailed information on any topic, refer to the specific documentation files in /docs/agent/.