skills/wp-patterns/SKILL.md
Generate technically correct, design-distinctive WordPress block patterns. Use when creating block patterns, starter page patterns, template patterns, template part patterns, or improving pattern design quality. Covers pattern registration (PHP headers, auto/manual), block markup syntax, theme.json design tokens, categories, template types, accessibility, and i18n/escaping.
npx skillsauth add WordPress/agent-skills wp-patternsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use this skill when creating, updating, or reviewing WordPress block patterns such as:
patterns/*.phpTemplate TypesGenerate production-grade patterns that are technically correct, design-distinctive, theme-compatible, and accessible. If the user is building a custom block, changing block.json, or adding dynamic rendering, use wp-block-development instead. If the user needs frontend interactivity, use wp-interactivity-api.
theme.json presets for colors, typography, spacing, layout, and gradients.Before writing any pattern, internalize these constraints:
Block markup only — all visual design is expressed through block comment attributes and theme.json presets. No inline <style> tags, no custom CSS classes, no arbitrary HTML outside of block wrappers.
No JavaScript — patterns are static block markup. For interactivity, use blocks that natively support it (Navigation, Search, Query Loop). Never inject <script> tags.
PHP runs at init, not render — pattern files execute PHP once during registration. Never use query-dependent functions (get_posts(), the_title(), wp_get_current_user()). Safe: esc_html_e(), get_theme_file_uri(). Read references/pattern-registration.md for registration-time PHP constraints.
Always escape — every PHP output must use esc_html__(), esc_attr__(), or esc_url(). No raw echo of user-facing strings. Read references/pattern-registration.md for safe PHP output functions.
Always i18n — every user-visible string must be wrapped in a translation function with the theme/plugin text domain. Use esc_html_e() (echo + escape + translate) or esc_html__() (return + escape + translate). Read references/pattern-registration.md for text domain and i18n examples.
Prefer presets over hardcoded values — use "backgroundColor":"primary" not "style":{"color":{"background":"#0073aa"}}. Presets adapt to theme changes and style variations.
Valid nesting — every opening <!-- wp:block --> must have a matching <!-- /wp:block -->. Nesting must be properly ordered. Self-closing blocks use <!-- wp:block /-->.
Use native blocks for behavior — use Query Loop, Search, Navigation, Social Icons, or an existing form block instead of custom PHP/HTML behavior. For newsletter, donation, payment, or map behavior, create a CTA/placeholder or use an existing block/plugin; do not invent forms, iframes, scripts, or third-party processing.
Prefer local assets — use theme/plugin assets with get_theme_file_uri() and esc_url(). Avoid external placeholder image URLs unless the user explicitly approves them.
Reference: references/block-markup-reference.md for syntax, references/anti-patterns.md for what to avoid.
node skills/wp-project-triage/scripts/detect_wp_project.mjsnode skills/wp-block-themes/scripts/detect_block_themes.mjspatterns/ directory or needs manual plugin registration.If the user did not provide required inputs, infer only low-risk defaults. Ask before inventing a theme slug, text domain, asset path, custom post type, taxonomy, event date field, or theme-specific preset. If theme.json is missing or presets cannot be verified, use conservative core presets or ask before using theme-specific slugs.
Before writing markup, make 5 deliberate design decisions. This is what separates distinctive patterns from generic AI output.
Reference: references/design-with-tokens.md for translating decisions to block attributes.
What does this pattern achieve for the end user? A hero converts visitors. A testimonial grid builds trust. A pricing table drives comparison. Let purpose drive every subsequent choice.
Choose a clear direction and map it to block attributes:
| Tone | Color Strategy | Typography | Layout | |------|---------------|------------|--------| | Bold/energetic | High contrast, accent backgrounds, gradients | XX-large headings, tight letter-spacing, uppercase accents | Full-width, asymmetric columns, large padding | | Minimal/refined | Base + contrast only, subtle tertiary sections | Restrained sizes, generous line-height | Constrained width, generous whitespace, centered | | Editorial/magazine | Dark sections alternating with light | Mixed font families, varied heading scales | Asymmetric splits (66/33), media-text blocks | | Playful/creative | Multiple accent colors, bright backgrounds | Large display sizes, varied weights | Grid layouts, unexpected column ratios, rounded corners | | Corporate/professional | Neutral palette, primary for CTAs only | Consistent scale, body font dominant | Equal columns, structured grid, minimal decoration |
Choose your primary layout strategy:
Vary spacing intentionally:
blockGap (spacing|20-30) for related elements within a cardblockGap (spacing|40) for flowing contentPlan your type scale before writing markup:
fontSize:"xx-large" + fontFamily:"heading" + tight lineHeightfontSize:"x-large" + fontFamily:"heading"fontSize:"large" + textColor:"secondary" or fontFamily:"body"fontSize:"medium" or defaultfontSize:"small" + textColor:"secondary"Add at least one typographic accent:
Plan section-by-section color flow:
base background, contrast text (default)contrast background, base text (inverted)primary or tertiary backgroundA pattern with multiple sections should vary backgrounds — don't use the same background for every section.
Block Types: core/post-content unless the pattern is specifically for a template or template part.Template Types and use Inserter: no when the pattern should only be offered in template replacement flows.core/query with core/post-template, post title/excerpt/date/featured image blocks, pagination, and core/query-no-results where relevant. For archive, search, category, and author templates, prefer inherited query context instead of custom PHP. For CPT/event queries, confirm the post type slug, taxonomy/date assumptions, and available blocks before generating markup.Use these composition moves when the request calls for a visually distinctive pattern:
0 unless the design specifically needs a tracked wordmark.These moves should still pass the technical checklist: valid block markup, translatable/escaped strings, local or approved assets, accessible labels, no scripts, no inline <style> tags, and no custom CSS classes.
Sketch the nesting tree before writing markup. Example for a hero pattern:
Group (full-width, constrained layout, dark bg, vertical padding 80)
Group (constrained inner, flex vertical, center align)
Paragraph (uppercase label, small, letter-spacing, accent color)
Heading (h2, xx-large, heading font, tight line-height)
Paragraph (lead text, large, secondary color)
Buttons (flex, center)
Button (primary bg, base text)
Button (outline style)
This step catches nesting errors and ensures intentional hierarchy before you write a single comment tag.
Assemble the PHP header and block markup.
File header (for theme auto-registration):
<?php
/**
* Title: [Descriptive Name]
* Slug: theme-slug/pattern-name
* Categories: [comma-separated slugs]
* Keywords: [search terms]
* Viewport Width: 1400
* Block Types: [if starter/template part pattern]
* Template Types: [if template pattern]
*/
?>
Reference: references/pattern-registration.md for all header fields and PHP rules.
Reference: references/pattern-categories-and-types.md for category selection and template types.
For plugin or conditional patterns, register manually on init with register_block_pattern(). Use translated title, description, and keywords; keep content static block markup; and avoid runtime queries. Register custom categories before using them with register_block_pattern_category() or define theme-owned categories in theme.json. For WordPress versions before filesystem auto-registration support, use manual registration instead of patterns/*.php auto-discovery.
Block markup body:
esc_html_e() for all visible textesc_url( get_theme_file_uri() ) for theme imagesReview against anti-patterns (references/anti-patterns.md):
<!-- wp:block --> has matching <!-- /wp:block -->esc_html_e() or esc_html__()esc_url()esc_attr_e() or esc_attr__()Slug in header uses correct namespace: theme-slug/pattern-name<style>, no <script>, no custom CSS classesSlug unless intentionally creating a new patternTest the pattern in a real WordPress environment:
Using WordPress Playground (recommended):
npx @wp-playground/cli@latest server --auto-mount
Mount the theme directory and verify:
templateLock is used, locked elements resist editingFor template patterns, verify the Site Editor offers the pattern in the expected template replacement flow. If Inserter: no is used, confirm it is hidden from the general inserter but still available where intended.
Manual check:
Run the repo's existing lint, build, or test commands if the pattern change touches assets, generated files, or registration code.
When updating an existing pattern, remember that inserted pattern content is copied into posts/templates. Changing the pattern file does not retroactively update already inserted content, and changing block names or saved markup can create recovery prompts for newly inserted content.
For PR or package review, confirm the diff is scoped to the intended pattern files, references, scripts, and eval scenarios. Do not mix unrelated repo updates into a pattern change.
Start with references/block-markup-reference.md, references/pattern-registration.md, and references/anti-patterns.md.
Common failures:
Title, Slug, and Categories headers; confirm the file is under patterns/*.php; confirm Inserter: no is not hiding it.theme-slug/pattern-name or plugin-slug/pattern-name.esc_html_e(), esc_html__(), esc_attr_e(), esc_attr__(), or esc_url() as appropriate.get_posts(), the_title(), wp_get_current_user()) and use blocks such as Query Loop instead.core/post-template, post title/excerpt/date/image blocks, pagination when needed, and core/query-no-results fallback.theme.json; avoid unsupported theme-specific slugs unless documented.init, categories are registered before patterns, and pattern content remains static block markup.Stop and ask for help or consult canonical docs when:
wp-block-development.wp-interactivity-api.Use WordPress Developer Resources, the Theme Handbook, and the Block Editor Handbook for upstream behavior before inventing version-sensitive guidance.
"Create a bold hero pattern with a large heading, subtitle, and two CTA buttons. Dark background, full-width, for a creative agency theme."
Expected: Cover or Group block with contrast bg, constrained inner, heading with xx-large + heading font, paragraph with secondary color, Buttons with primary + outline styles.
"Create a 3-column testimonial grid with avatar, quote, name, and role. Alternating card backgrounds."
Expected: Group wrapper, block-native grid or Columns layout (3 columns, responsive), inner Group cards with varied tertiary/base backgrounds, Image block for avatar (rounded border-radius), Paragraph for quote (italic), Heading h3 for name, Paragraph small for role.
"Create a starter page pattern for a blog index with featured post hero and 3-column grid of recent posts below."
Expected: Block Types: core/post-content header, Query Loop for featured post (perPage 1, large layout), second Query Loop for grid (perPage 3, grid layout with post-template), clear visual separation between sections.
"Create a 4-column footer pattern with logo, navigation links, contact info, and social icons. Dark background."
Expected: Block Types: core/template-part/footer header, Group full-width with contrast bg, Columns (4), Site Logo block, Navigation or list blocks, Paragraph blocks for contact, Social Icons block. Inserter: no.
development
Use when the deliverable is WordPress Playground Blueprint JSON or a Blueprint bundle, including creating, editing, reviewing, validating schema keys, choosing steps/resources, and debugging Blueprint files. For only running or sharing a Playground environment, use wp-playground.
tools
Use as the WordPress Playground routing wrapper for ambiguous Playground work, local CLI runs with @wp-playground/cli, playground.wordpress.net share links, browser previews, snapshots, mounts, version switching, and Xdebug. For Blueprint JSON authoring or review, use the blueprint skill directly.
development
Use when developing WordPress block themes: theme.json (global settings/styles), templates and template parts, patterns, style variations, and Site Editor troubleshooting (style hierarchy, overrides, caching).
tools
Use when the user asks about WordPress codebases (plugins, themes, block themes, Gutenberg blocks, WP core checkouts) and you need to quickly classify the repo and route to the correct workflow/skill (blocks, theme.json, REST API, WP-CLI, performance, security, testing, release packaging).