Skip to content

Repository files navigation

WordPress Pattern Toolkit

Scaffolding, compliance checking, and HTML template validation for WordPress FSE block themes.

Generates block pattern PHP files, layout patterns, and style variations. Checks pattern .php files for structural and naming rule violations, and checks HTML template/part files for client-side block validation drift — no WordPress context required. Runs on the host machine as a standalone PHP CLI tool.

Installation

As a global tool:

composer global require imagewize/pt-cli

Or as a project dev dependency (recommended for theme development):

composer require --dev imagewize/pt-cli

Then use ./vendor/bin/pt-cli or add a Composer script.

Requires PHP 8.1+.

Usage

Scaffolding Commands

# List available templates, snippets, categories, and style variations
pt-cli list
# Scaffold a new pattern from a template
pt-cli pattern:create --title="My Hero" --slug=my-hero --template=hero-cover --category=elayne/hero
# Scaffold a layout pattern
pt-cli layout:create --title="Landing Page" --slug=landing --layout=landing-page --category=elayne/pages
# Scaffold a theme style variation
pt-cli style:create --name="Ocean Legal" --vertical=legal
# Full interactive mode (no options = prompts)
pt-cli pattern:create

Compliance Checking

# Check all patterns in a directory
pt-cli check /path/to/patterns
# Check with a specific theme config
pt-cli check /path/to/patterns --theme=elayne
# Check a single file
pt-cli check /path/to/patterns/header-default.php --theme=elayne
# Apply mechanical autofixes
pt-cli check /path/to/patterns --theme=elayne --autofix

HTML Template Compliance

# Check all .html files in a templates or parts directory
pt-cli check:templates /path/to/templates/ --theme=elayne
pt-cli check:templates /path/to/parts/ --theme=elayne
# Check a single template file
pt-cli check:templates /path/to/templates/archive-product.html --theme=elayne
# Apply mechanical autofixes (taxQuery:{} → [] and template-part theme attribute)
pt-cli check:templates /path/to/templates/ --theme=elayne --autofix

Pattern Diff & Sync

Compare a Gutenberg clipboard paste against an existing PHP pattern file, or apply the changes back while preserving all PHP translation wrappers.

# Report differences only (shows missing translations, editor attrs, CSS issues)
pbpaste | pt-cli pattern:diff patterns/woo-signature-pieces.php --from-stdin
# Include fix suggestions in the diff report
pbpaste | pt-cli pattern:diff patterns/woo-signature-pieces.php --from-stdin --show-suggestions
# Output diff results as JSON (for tooling integration)
pbpaste | pt-cli pattern:diff patterns/woo-signature-pieces.php --from-stdin --json
# Preview the merged result without touching the file
pbpaste | pt-cli pattern:diff patterns/woo-signature-pieces.php --from-stdin --apply --dry-run
# Apply clipboard changes to the PHP file (preserves esc_html_e, esc_attr_e, etc.)
pbpaste | pt-cli pattern:diff patterns/woo-signature-pieces.php --from-stdin --apply
# Lower the similarity threshold for loosely matched blocks (default: 0.95)
pbpaste | pt-cli pattern:diff patterns/woo-signature-pieces.php --from-stdin --similarity-threshold=0.80

What --apply does:

  1. Strips editor-only attributes (__privatePreviewState) from block JSON.
  2. Fixes bare font-size slug values (font-size:small) → CSS variable (font-size:var(--wp--preset--font-size--small)).
  3. Removes nested <p> copy artefacts introduced by the Gutenberg clipboard.
  4. Re-maps every text node back to its original PHP wrapper (esc_html_e, esc_attr_e, wp_kses_post) from the existing file.
  5. Generates a new esc_html_e() wrapper for any text that is new in the clipboard.
  6. Preserves the PHP docblock header unchanged.

The file is only written when --apply is used without--dry-run.

Commands Reference

CommandDescription
list (default)List available templates, snippets, categories, and style variations
pattern:createScaffold a new Elayne block pattern from a template
layout:createScaffold a new Elayne block layout pattern
style:createScaffold a WordPress theme style variation JSON
checkCheck PHP pattern files for compliance violations
check:templatesCheck HTML template/part files for block validation drift
pattern:diffDiff Gutenberg clipboard against a pattern file, or apply changes preserving PHP

Workflow

pt-cli is an all-in-one tool for WordPress FSE block theme development:

Scaffolding Workflow

StepToolPurposeWhere
1pt-cli pattern:create or pt-cli layout:createGenerate pattern/layout scaffoldingHost
2Build in WP editorCreate pattern contentVM
3Copy blocksCopy all blocks from editorVM
4pt-cli pattern:create --shell-onlyCreate PHP file with paste markerHost
5Replace markerPaste blocks into pattern fileHost

Pattern Sync Workflow (updating existing patterns)

When an existing PHP pattern needs updating from the Site Editor, use pattern:diff --apply instead of pasting manually — it keeps all esc_html_e() and other PHP wrappers intact.

StepCommandPurpose
1Edit pattern in Site EditorMake structural/layout changes
2Copy all blocks (Cmd+A, Cmd+C)Copy updated block HTML to clipboard
3pbpaste | pt-cli pattern:diff <file> --from-stdin --apply --dry-runPreview merged result
4pbpaste | pt-cli pattern:diff <file> --from-stdin --applyWrite merged result to file
5pt-cli check <file> --theme=elayneVerify compliance passes

Compliance Workflow (three-pass)

PassToolPurposeWhere
1wp pattern validate --fixStructural validation (WordPress parser — unbalanced delimiters, malformed JSON, bad nesting)VM
2pt-cli check --theme=elaynePHP pattern compliance (hardcoded values, naming rules, WooCommerce block structure)Host
3pt-cli check:templates --theme=elayneHTML template compliance (WooCommerce save() drift, taxQuery, template-part theme attribute)Host

Pass 1 requires WordPress (database connection) and runs in the Trellis VM. Passes 2 and 3 are standalone and run on the host machine.

Templates

23 pre-built pattern templates covering common use cases:

TemplateDescription
blankEmpty pattern with header only
hero-coverFull-bleed wp:cover with bottom-center content
cta-fullwidthFull-width call-to-action band
feature-grid-3colFull-width section with 3 feature cards
stats-bar-fullwidthDark full-width stats/numbers bar
two-column-text-imageText left, image right two-column layout
header-standardStandard header — logo, navigation, social links
footer-standardStandard footer — brand blurb, nav columns, subnav
testimonials-gridResponsive testimonial card grid with reviewer info
pricing-comparisonThree-tier pricing table with elevated recommended card
blog-post-columnswp:query-driven 3-column post grid (portrait images)
team-gridTeam member profile grid — photo, name, title, bio

WooCommerce templates:

TemplateDescription
woo-heroTwo-column hero: text + CTA left, decorative cover right
woo-tickerServer-rendered marquee ticker bar (needs render_block filter)
woo-shop-categoriesCSS bento grid: one large featured card + four smaller cards
woo-featured-productsSection header with View All + product-collection 4-col grid
woo-our-storyTwo-column brand story: monogram watermark left, text + stats right
woo-testimonialsThree-column testimonial cards with star ratings and avatar circles
woo-newsletterFull-bleed newsletter signup with decorative eyebrow
woo-shop-landingStore homepage shell that composes sub-patterns in sequence
woo-cartFull-width cart page wrapper (Inserter: false)
woo-checkoutFull-width checkout page wrapper (Inserter: false)
woo-filters-sidebarSticky sidebar: price slider + colour-chip attribute + two checkbox-list attributes
woo-product-gridFilter-aware product-collection grid with sort toolbar + pagination

Layouts

8 layout skeletons for rapid page construction:

LayoutDescription
full-widthSingle column, constrained — simplest starting point
two-column50/50 columns block
three-columnGrid with 3 equal groups
sidebar-leftNarrow left sidebar (33%) + wide content area (66%)
sidebar-rightWide content area (66%) + narrow right sidebar (33%)
hero-image-leftCover image left + heading, text, CTA right
hero-image-rightHeading, text, CTA left + cover image right
landing-pageHero + 3-column features + CTA — no header/footer wrapper

Style Variations

5 preset color palettes for common business verticals:

VerticalColor Scheme
customEnter your own hex color values
legalNavy blue + gold
plumbingDark blue + orange
spaSage green + sand
food-beverageBurgundy + gold

Snippets

13 reusable code snippets for common pattern components:

SnippetDescription
eyebrow-heading-body.txtEyebrow label + heading + body paragraph
3col-grid-wrapper.txtResponsive 3-column grid wrapper
stat-item.txtNumber + label stat card (dark background)
testimonial-card.txtTestimonial with stars, quote, author
two-button-group.txtPrimary + outline button pair
overlay-grid-cover-card.txtPortrait cover image card + floating badge (use wp:cover, NOT wp:image)
valid-cover.txtwp:cover with all required attrs: dimRatio, backgroundColor/customGradient, minHeight (root integer) + minHeightUnit
valid-columns-wp66.txtwp:columns without inline gap/margin; isStackedOnMobile:false → is-not-stacked-on-mobile class
responsive-grid-min-width.txtwp:group grid layout with minimumColumnWidth — preferred over wp:columns for 3+ columns
valid-button-attr-order.txtwp:button with className/colors before style; font size via style.typography.fontSize
valid-fullwidth-section.txtalignfull outer group + margin reset (top/bottom:"0" no units) + constrained inner group
valid-heading-with-preset.txtwp:heading with fontSize slug in JSON and matching has-{slug}-font-size utility class in HTML

Configuration

Built-in configs ship with the tool:

  • base — default rules for any FSE theme
  • elayne — Elayne-specific rules (extends base)

Project-level override

Create .pt-cli/{theme}.json in your project root to override or extend the built-in config without needing a pt-cli release:

my-project/
├── .pt-cli/
│ └── elayne.json
└── web/app/themes/elayne/
└── patterns/

Config lookup order:

  1. .pt-cli/{theme}.json (project directory)
  2. config/{theme}.json (tool directory)
  3. config/base.json (fallback)

Rules

Base rules (all FSE themes)

RuleAutofixableSeverity
No hardcoded font sizes (CSS px/rem/em)NoError
No spacer blocksNoError
Margin reset on alignfull patternsNoError
Balanced HTML tags (<div>, <ul>, <ol>, <li>, <figure>, etc.)NoError
Responsive grid for 3+ columns (warn on wp:columns)NoWarning
No hardcoded media IDsNoError
Translated strings (HTML tags + alt attributes)NoError
Proper patternName in outermost block metadataNoError
No HTML comments between opening tags and block commentsNoError
No custom domain emails (use example@example.com)NoError
No hardcoded external URLs in src attributesNoError
wp:button root fontSize must use style.typographyNoError
wp:buttonclassName must come before style in JSONNoError
Cover block minHeight must have root-level unitsNoError
No empty border side objects {} in block JSONNoError
wp:buttons must have <div class="wp-block-buttons"> wrapperNoError
No overflow:hidden as inline style on group blocksNoError
No opacity as inline style on HTML elementsNoError
Font preset classes match root-level fontSize/fontFamilyNoError
No stale inline blockGap/gap/margin on group/column wrappersNoError

Elayne-specific rules (--theme=elayne)

RuleAutofixableSeverity
wp:template-part must have "theme":"elayne" attributeNoError
patternName prefix must start with elayne/NoError
No emoji iconsNoWarning
woocommerce/product-title inside product-template must use post-title + __woocommerceNamespaceNoError
WC native blocks must not have __woocommerceNamespaceNoError
woocommerce/product-collection must have query metadataNoError
woocommerce/product-collection must have <div class="wp-block-woocommerce-product-collection"> wrapperNoError
woocommerce/product-collection must not have both layout and displayLayoutNoError

Autofixable rules (--autofix)

Rule
Strip inline gap: from groups/columns
Strip inline margin: from flex groups/columns
Reorder button JSON keys (className before style)
Migrate button root fontSize to style.typography
Inject has-{slug}-font-size class on heading/paragraph

Exceptions

  • Templates (template-*, header-*, footer-*) allow: border-radius:5px, border-radius:100px, blockGap:0.5rem, blockGap:10px
  • WooCommerce plugin patterns (wp-content/plugins/woocommerce/patterns/*) are exempt from all checks

Template rules (check:templates)

Applied to .html files in templates/ and parts/ directories. These checks catch client-side JavaScript save() mismatches that the PHP compliance checker and WP-CLI structural validator cannot detect.

RuleAutofixableSeverity
taxQuery:{} must be taxQuery:[] (object → array)YesError
WooCommerce filter sub-blocks must have an HTML <div> wrapperNoError
woocommerce/product-filters<div> must include WooCommerce CSS custom propertiesNoError
wp:template-part must declare "theme":"<slug>"YesWarning
Balanced HTML tags (<div>, <ul>, <ol>, <li>, etc.)NoError

Why separate from check?

The check command processes PHP pattern files. HTML template files use a different structure — raw block markup without PHP wrappers — and require different checks. In particular, WooCommerce 9.x+ changed the save() output for filter blocks to include empty <div> wrappers; templates written against older versions lack those wrappers and trigger client-side block validation errors that neither WP-CLI nor the PHP checker can catch.

Demo Rebuild Script

For rebuilding demo pages from pattern PHP files, see the Demo Rebuild Script guide.

Development

git clone https://github.com/imagewize/pt-cli
cd pt-cli
composer install
bin/pt-cli list
bin/pt-cli check --help

License

MIT — see LICENSE.

About

Pattern scaffolding and compliance checker for WordPress FSE block themes.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages