229 lines
9.1 KiB
Markdown
229 lines
9.1 KiB
Markdown
# WP Theme Dev
|
|
|
|
Use this skill for general Websimple WordPress theme PHP development conventions.
|
|
|
|
Do not use this skill for PHPCS tooling setup or formatting commands; use `references/wp-code-style.md`. Use `references/wp-browser.md` for visual/frontend checks and `references/wp-xdebug.md` for runtime PHP debugging.
|
|
|
|
## Scope boundaries
|
|
|
|
This skill covers:
|
|
|
|
- theme PHP file/folder organization;
|
|
- `functions.php` organization;
|
|
- actions and filters;
|
|
- function naming and namespacing/prefixing;
|
|
- template conventions for regular WordPress themes;
|
|
- comments/docblocks style;
|
|
- escaping, sanitization, translation, and preferred output syntax;
|
|
- safe PHP/theme refactoring workflow.
|
|
|
|
Defer specialized areas to dedicated skills when they apply:
|
|
|
|
- Kaliroots child themes: use/refine the `references/wp-kaliroots.md` conventions instead of this skill's template guidance.
|
|
- PHPCS/PHPCBF/tooling: use `references/wp-code-style.md`.
|
|
- ACF architecture/conventions: use `references/wp-acf.md`.
|
|
- Asset pipeline details, bundler config, and build commands: use `references/wp-assets.md`.
|
|
- Vue/React/headless conventions beyond source placement: use dedicated skills when available.
|
|
|
|
## Theme structure
|
|
|
|
Prefer small, discoverable theme files over large catch-all files.
|
|
|
|
- Keep all PHP logic under `includes/`, grouped by category.
|
|
- Keep `functions.php` as a categorized bootstrap/loader for `includes/` files.
|
|
- Use category directories such as `includes/admin/`, `includes/core/`, `includes/cpt/`, `includes/taxonomies/`, `includes/forms/`, `includes/roles/`, `includes/schemas/`, `includes/sections/`, `includes/shortcodes/`, `includes/vendors/`, `includes/widgets/`, and `includes/woocommerce/` as applicable.
|
|
- Keep helpers/utilities separate from hook callback registration when practical.
|
|
- Use `src/` for CSS/SCSS, JavaScript, TypeScript, Vue, React, and similar source assets that are compiled or bundled.
|
|
- Preserve the existing project structure unless the user asks for reorganization.
|
|
- Do not introduce a new architecture into an established theme without approval.
|
|
|
|
Preferred `functions.php` pattern: keep it as a categorized loader for files under `includes/`.
|
|
|
|
```php
|
|
<?php
|
|
|
|
// Administration
|
|
require_once __DIR__ . '/includes/admin/attachment.php';
|
|
require_once __DIR__ . '/includes/admin/user.php';
|
|
|
|
// Core
|
|
require_once __DIR__ . '/includes/core/assets.php';
|
|
require_once __DIR__ . '/includes/core/helpers.php';
|
|
require_once __DIR__ . '/includes/core/theme-setup.php';
|
|
|
|
// Custom Post Types
|
|
require_once __DIR__ . '/includes/cpt/project.php';
|
|
|
|
// Custom Taxonomies
|
|
require_once __DIR__ . '/includes/taxonomies/project-category.php';
|
|
|
|
// Roles
|
|
require_once __DIR__ . '/includes/roles/editor.php';
|
|
|
|
// Shortcodes
|
|
require_once __DIR__ . '/includes/shortcodes/alert.php';
|
|
|
|
// Vendors
|
|
require_once __DIR__ . '/includes/vendors/acf.php';
|
|
require_once __DIR__ . '/includes/vendors/gravityforms.php';
|
|
require_once __DIR__ . '/includes/vendors/polylang.php';
|
|
require_once __DIR__ . '/includes/vendors/tinymce.php';
|
|
|
|
// Widgets
|
|
require_once __DIR__ . '/includes/widgets/contact-info.php';
|
|
|
|
// WooCommerce
|
|
require_once __DIR__ . '/includes/woocommerce/cart.php';
|
|
require_once __DIR__ . '/includes/woocommerce/checkout.php';
|
|
require_once __DIR__ . '/includes/woocommerce/product.php';
|
|
```
|
|
|
|
Keep empty category headers when they make the intended structure clearer or match the project convention.
|
|
|
|
Avoid modifying WordPress core, vendor directories, uploads, caches, compiled assets, or unrelated themes.
|
|
|
|
## Templates and template parts
|
|
|
|
For themes that are child themes of Kaliroots, do not apply generic template conventions. Refer to `references/wp-kaliroots.md` instead.
|
|
|
|
For regular WordPress themes, templates should live under `templates/` and be grouped by rendering purpose:
|
|
|
|
```text
|
|
templates/
|
|
html/ # outer high-level templates
|
|
site/ # global site header/footer and site-wide layout parts
|
|
content/ # content-related templates
|
|
loops/ # loop wrappers and loop item templates
|
|
emails/ # outgoing email templates
|
|
```
|
|
|
|
Each template group may have a `partials/` subdirectory for smaller local partials.
|
|
|
|
Use `templates/content/loops/` for loop templates. Prefer paired names where the outer loop and item template share a base name:
|
|
|
|
```text
|
|
templates/content/loops/events.php
|
|
templates/content/loops/events-item.php
|
|
templates/content/loops/posts.php
|
|
templates/content/loops/posts-item.php
|
|
```
|
|
|
|
Additional conventions:
|
|
|
|
- Use WordPress template hierarchy intentionally.
|
|
- Keep template files readable and focused on rendering.
|
|
- Use template parts for repeated markup or meaningful sections.
|
|
- Prefer clear names that describe the rendered section or component.
|
|
- Keep heavy data preparation, custom queries, and complex conditionals out of templates when a helper or setup function would make the template clearer.
|
|
- Keep markup/output close to templates and reusable data/logic close to `includes/` helpers/modules.
|
|
|
|
Do not mass-reorganize template files without explicit approval.
|
|
|
|
## Actions and filters
|
|
|
|
Register hooks in predictable locations, following the theme's existing organization.
|
|
|
|
- Prefer named callbacks over anonymous closures when the callback is reused, non-trivial, or likely to need debugging.
|
|
- Use clear project/theme-prefixed or namespaced callback names.
|
|
- Keep callback names tied to the hook purpose.
|
|
- Avoid hidden side effects in filters unless intentional and documented by context.
|
|
- Preserve important priorities and accepted-argument counts.
|
|
- Document or call out non-obvious hook ordering dependencies.
|
|
|
|
Example pattern:
|
|
|
|
```php
|
|
// Enqueue theme assets.
|
|
add_action( 'wp_enqueue_scripts', 'example_enqueue_assets' );
|
|
function example_enqueue_assets(): void {
|
|
wp_enqueue_style(
|
|
'example-theme',
|
|
get_stylesheet_directory_uri() . '/dist/css/theme.css',
|
|
[],
|
|
wp_get_theme()->get( 'Version' )
|
|
);
|
|
}
|
|
|
|
// Add a body class on the front page.
|
|
add_filter( 'body_class', 'example_add_body_classes' );
|
|
function example_add_body_classes( array $classes ): array {
|
|
if ( is_front_page() ) {
|
|
$classes[] = 'is-front-page';
|
|
}
|
|
|
|
return $classes;
|
|
}
|
|
```
|
|
|
|
When refactoring hooks, verify behavior with the smallest meaningful check: WP-CLI, browser smoke test, or Xdebug when needed.
|
|
|
|
## Function naming
|
|
|
|
Follow the existing theme convention first. When adding new global functions, avoid generic names.
|
|
|
|
Prefer one of:
|
|
|
|
- a theme/project prefix, e.g. `example_get_hero_title()`;
|
|
- a namespace if the theme already uses namespaces;
|
|
- a class/static method only when the theme already uses that style or it genuinely improves organization.
|
|
|
|
Keep helper names descriptive. Separate hook callbacks from pure/data helpers when it improves readability.
|
|
|
|
## Comments and docblocks
|
|
|
|
Keep the project's existing commenting style coherent.
|
|
|
|
Comments may be explicit and simple, including human-readable descriptions of what a function does. Do not remove comments just because they restate the function name if that style is consistent in the project.
|
|
|
|
Use comments/docblocks to improve scanability and clarify intent, inputs, outputs, side effects, or hook context when useful. Avoid stale, misleading, or decorative comments.
|
|
|
|
## Escaping, sanitization, translation, and output syntax
|
|
|
|
Escape dynamic values at output time unless WordPress or the data source has already produced safe markup for that exact context.
|
|
|
|
Common choices:
|
|
|
|
- `esc_html()` for plain text;
|
|
- `esc_attr()` for attribute values;
|
|
- `esc_url()` for URLs;
|
|
- `wp_kses_post()` for trusted post-like HTML;
|
|
- `wp_json_encode()` for JSON output.
|
|
|
|
Sanitize input before saving or using it in queries. Use WordPress translation helpers for user-facing theme strings when appropriate.
|
|
|
|
Prefer compact PHP output tags for template output:
|
|
|
|
```php
|
|
<?= esc_html( $title ); ?>
|
|
<?= esc_url( $url ); ?>
|
|
<?= wp_kses_post( $content ); ?>
|
|
```
|
|
|
|
Do not rewrite existing `<?php echo ...; ?>` output solely for style unless the user asked for cleanup or the surrounding file is already being touched.
|
|
|
|
## Data and query conventions
|
|
|
|
- Use core WordPress APIs where possible.
|
|
- Reset post data after custom `WP_Query` loops.
|
|
- Avoid relying on surprising global state.
|
|
- Avoid expensive queries inside repeated template parts.
|
|
- Add caching only when justified by a concrete performance issue.
|
|
|
|
## Refactoring workflow
|
|
|
|
1. Inspect the theme structure, active child/parent theme relationship, and existing conventions.
|
|
2. If the theme is a Kaliroots child theme, defer template decisions to Kaliroots-specific conventions.
|
|
3. Make small coherent changes that preserve behavior unless the user requested redesign.
|
|
4. Avoid mixing formatting-only and behavior changes.
|
|
5. Run lint/style checks via `references/wp-code-style.md` when PHP files changed.
|
|
6. Use `references/wp-browser.md` for frontend smoke checks when templates/output changed.
|
|
7. Use `references/wp-xdebug.md` when runtime behavior is unclear.
|
|
8. Inspect the diff before claiming success.
|
|
|
|
## Safety
|
|
|
|
- Do not mass-reorganize a theme without explicit approval.
|
|
- Do not touch core, vendor, uploads, caches, compiled assets, or unrelated themes.
|
|
- Do not silently force conventions when the existing project clearly uses a different coherent pattern; call out the tradeoff.
|
|
- Keep changes reversible and scoped to the user's request.
|