feat: Initial Claude skills for websimple-devops

This commit is contained in:
2026-05-26 10:42:20 -04:00
commit a37c19bb87
16 changed files with 2228 additions and 0 deletions

271
references/wp-acf.md Normal file
View File

@@ -0,0 +1,271 @@
# WP ACF
Use this skill for Websimple WordPress projects that use Advanced Custom Fields.
Use `references/wp-theme-dev.md` for general PHP/theme structure, `references/wp-code-style.md` for PHPCS/PHPCBF, `references/wp-browser.md` for visual checks, and `references/wp-xdebug.md` for runtime debugging.
## Core principles
- Keep ACF configuration predictable, portable, and version-controlled.
- Prefer clear field names that map naturally to template usage.
- Keep field registration/ACF hooks under `includes/vendors/acf.php` or the existing ACF vendor/module file.
- Keep rendering logic in templates and reusable data helpers under `includes/` when needed.
- Avoid changing field keys, field names, return formats, or option names casually; these may affect stored content.
## Local JSON
ACF field group JSON definitions should live under the active theme's `acf-json/` directory.
- Keep ACF JSON files version-controlled.
- Preserve the project's existing JSON directory if one exists.
- For greenfield projects, use `acf-json/` at the theme root.
- Ensure the `acf-json/` directory exists and is writable by WordPress.
- Do not delete or regenerate ACF JSON files without checking the diff.
When local JSON is enabled, saving a field group, post type, taxonomy, or options page in wp-admin automatically creates or updates its JSON file. Do not tell the user to manually re-export JSON after normal dashboard saves; instead, remind them to review and commit the changed JSON file.
There is no expected per-field-group `json_sync` flag in Websimple conventions. ACF local JSON is controlled by ACF's global JSON setting and save/load paths. ACF defaults local JSON on and uses the active theme's `acf-json/` folder unless customized.
If PHP hooks customize ACF JSON paths, keep them in the ACF vendor/module file, e.g. `includes/vendors/acf.php`.
## Field group keys and filenames
For greenfield field groups, use deterministic field group keys instead of ACF's auto-generated group keys.
The field group key should match the JSON filename and describe what the group targets:
```text
acf-json/group_post_project.json
key: group_post_project
```
Examples:
```text
group_post_project # fields for the project custom post type
group_page_home # fields for the home page/template
group_options_site # site options fields
group_taxonomy_sector # fields for the sector taxonomy
```
ACF field keys inside the group may remain auto-generated. The deterministic-key convention applies primarily to field groups so JSON files stay organized and easy to find.
For existing projects with auto-generated field group keys, preserve them unless the user explicitly approves a cleanup/migration. Do not rename existing field group keys casually because synced JSON, database references, and editor workflows may depend on them.
## Synchronizing ACF JSON
For ACF 6.8+ with WP-CLI available, prefer the built-in ACF JSON CLI commands.
Safe inspection:
```bash
wp acf json status
wp acf json sync --dry-run
```
Apply pending local JSON changes to the database:
```bash
wp acf json sync
```
Useful scoped variants:
```bash
wp acf json sync --type=field-group
wp acf json sync --key=group_post_project
```
Notes:
- `wp acf json sync` modifies the database; run `--dry-run` first, especially outside local development.
- The command syncs pending local JSON changes for ACF item types such as field groups, post types, taxonomies, and options pages.
- If no items are pending, expect an “already in sync” style result.
- Do not use a guessed `--all` flag; current ACF CLI sync defaults to all supported item types unless scoped with `--type` or `--key`.
If the project uses an older ACF/ACF PRO version without these commands:
1. Check the installed ACF version and whether an update is safe for the project.
2. If updating is low-risk and explicitly approved, update ACF/ACF PRO first, then use the CLI workflow.
3. Otherwise, use `references/wp-browser.md` to navigate wp-admin and sync from the ACF field group/admin screen.
For production or staging, ask before updating plugins or syncing database-backed ACF changes.
## Field group organization
Use field groups that reflect editorial concepts and template needs.
Common grouping patterns:
- page/template-specific fields;
- reusable section/component fields;
- site options;
- post type-specific metadata;
- taxonomy/user/menu-item metadata when needed.
Avoid dumping unrelated fields into a single large group. Prefer labels and instructions that make sense to editors.
## Field naming
Use stable, descriptive, snake_case field names.
Good examples:
```text
hero_title
hero_text
hero_image
cta_link
featured_posts
background_color
```
Avoid vague names like `title_2`, `content_block`, or `misc` unless the existing project convention requires it.
Do not rename existing field names unless the user accepts the content migration risk.
## Return formats
Respect existing return formats. Changing them can break templates.
Common preferences:
- image fields: use the format already expected by the theme; arrays are useful when templates need alt/title/sizes;
- link fields: arrays are usually practical for URL/title/target;
- post object / relationship fields: know whether the field returns IDs or objects before using it;
- true/false fields: handle empty/false explicitly.
When uncertain, inspect the field group JSON or runtime value before changing template code.
## Template usage
Prefer `get_field()` when the value needs escaping, conditionals, fallback handling, or reuse.
```php
<?php $title = get_field( 'hero_title' ); ?>
<?php if ( $title ) : ?>
<h1><?= esc_html( $title ); ?></h1>
<?php endif; ?>
```
Use compact output tags with escaping, following `references/wp-theme-dev.md`:
```php
<?= esc_html( get_field( 'eyebrow' ) ); ?>
<?= wp_kses_post( get_field( 'intro' ) ); ?>
```
Avoid `the_field()` for dynamic frontend output unless the value is known safe for the exact context. Prefer explicit escaping with `get_field()`.
For image arrays:
```php
<?php $image = get_field( 'hero_image' ); ?>
<?php if ( $image ) : ?>
<img
src="<?= esc_url( $image['url'] ); ?>"
alt="<?= esc_attr( $image['alt'] ?? '' ); ?>"
>
<?php endif; ?>
```
For link arrays:
```php
<?php $link = get_field( 'cta_link' ); ?>
<?php if ( $link ) : ?>
<a href="<?= esc_url( $link['url'] ); ?>" target="<?= esc_attr( $link['target'] ?: '_self' ); ?>">
<?= esc_html( $link['title'] ); ?>
</a>
<?php endif; ?>
```
## Options pages
Keep ACF options-page registration in the ACF vendor/module file.
Use options pages for true site-wide settings, not content that belongs to a page, post, taxonomy, or theme template.
When reading option fields, make the option scope explicit:
```php
<?php $phone = get_field( 'phone_number', 'option' ); ?>
```
## Flexible content and repeaters
Keep flexible content layouts readable and component-oriented.
- Use layout names that map to template partials or sections.
- Keep layout fields scoped to what the layout renders.
- Avoid deeply nested repeaters/flexible fields unless there is a strong editorial reason.
- For complex flexible content rendering, prefer dispatching to template parts instead of one giant template file.
The dispatch pattern depends on the theme. **Check whether the theme is a Kaliroots child theme first** (see `references/wp-kaliroots.md`) — Kaliroots has its own template lookup helpers and overriding them with generic WP dispatch fragments the resolution path.
For a **generic (non-Kaliroots) WordPress theme**:
```php
<?php if ( have_rows( 'sections' ) ) : ?>
<?php while ( have_rows( 'sections' ) ) : the_row(); ?>
<?php get_template_part( 'templates/content/sections/' . get_row_layout() ); ?>
<?php endwhile; ?>
<?php endif; ?>
```
For a **Kaliroots child theme**, dispatch through the Kaliroots section helper so child/parent override resolution works correctly:
```php
<?php if ( have_rows( 'sections' ) ) : ?>
<?php while ( have_rows( 'sections' ) ) : the_row(); ?>
<?= kaliroots_section_template( get_row_layout() ); ?>
<?php endwhile; ?>
<?php endif; ?>
```
In a Kaliroots project, the section partial then lives at `templates/content/sections/{layout-name}.php` and is located via Kaliroots' lookup pipeline — see `references/wp-kaliroots.md` for the helper set and naming rules.
Verify that the target partial exists before introducing either dispatch into an existing theme. If the project already uses a different established pattern, follow that — don't reorganize.
Inside the layout partial, use `get_sub_field()` (not `get_field()`) to read layout sub-fields, and escape at output:
```php
<?php
$heading = get_sub_field( 'heading' );
$image = get_sub_field( 'image' );
?>
<?php if ( $heading ) : ?>
<h2><?= esc_html( $heading ); ?></h2>
<?php endif; ?>
```
## Relationship and post object fields
Before using relationship/post object fields, confirm whether they return IDs or post objects.
- If using objects, restore global post state after setup.
- If using IDs, use explicit IDs with WordPress APIs.
- Avoid expensive relationship queries inside repeated templates when values can be prepared once.
## Refactoring workflow
1. Inspect the active theme, ACF plugin availability, existing ACF JSON path, and ACF-related include files.
2. Inspect existing field group JSON before changing field names, keys, return formats, or locations.
3. Keep PHP hooks/registration in the existing ACF module, usually `includes/vendors/acf.php`.
4. Keep template output escaped explicitly with `get_field()` where practical.
5. Make small, reversible changes.
6. After wp-admin field group edits, inspect the automatically updated `acf-json/` diff.
7. Run PHP lint/style checks via `references/wp-code-style.md` when PHP files changed.
8. Smoke-test affected frontend/admin behavior with `references/wp-browser.md` when relevant.
9. Inspect the diff, especially ACF JSON changes.
## Safety
- Do not rename existing field names or change return formats without calling out content/template impact.
- Do not delete ACF JSON files without explicit approval.
- Do not expose secrets from options pages or database values.
- Do not assume `the_field()` output is safe; escape based on context.
- Preserve the project's existing ACF structure when it is coherent.