Pattern scaffolding and compliance checker 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 — no WordPress context required. Runs on the host machine as a standalone PHP CLI tool.
As a global tool:
composer global require imagewize/pt-cliOr as a project dev dependency (recommended for theme development):
composer require --dev imagewize/pt-cliThen use ./vendor/bin/pt-cli or add a Composer script.
Requires PHP 8.1+.
# 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# 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| Command | Description |
|---|---|
list (default) |
List available templates, snippets, categories, and style variations |
pattern:create |
Scaffold a new Elayne block pattern from a template |
layout:create |
Scaffold a new Elayne block layout pattern |
style:create |
Scaffold a WordPress theme style variation JSON |
check |
Check pattern files for compliance violations |
pt-cli is an all-in-one tool for WordPress FSE block theme development:
| Step | Tool | Purpose | Where |
|---|---|---|---|
| 1 | pt-cli pattern:create or pt-cli layout:create |
Generate pattern/layout scaffolding | Host |
| 2 | Build in WP editor | Create pattern content | VM |
| 3 | Copy blocks | Copy all blocks from editor | VM |
| 4 | pt-cli pattern:create --shell-only |
Create PHP file with paste marker | Host |
| 5 | Replace marker | Paste blocks into pattern file | Host |
| Step | Tool | Purpose | Where |
|---|---|---|---|
| 1 | pt-cli check |
Generate pattern scaffolding | Host |
| 2 | wp pattern validate |
Structural validation (WordPress parser) | VM |
| 3 | pt-cli check --autofix |
Compliance checking with fixes | Host |
23 pre-built pattern templates covering common use cases:
| Template | Description |
|---|---|
blank |
Empty pattern with header only |
hero-cover |
Full-bleed wp:cover with bottom-center content |
cta-fullwidth |
Full-width call-to-action band |
feature-grid-3col |
Full-width section with 3 feature cards |
stats-bar-fullwidth |
Dark full-width stats/numbers bar |
two-column-text-image |
Text left, image right two-column layout |
header-standard |
Standard header — logo, navigation, social links |
footer-standard |
Standard footer — brand blurb, nav columns, subnav |
testimonials-grid |
Responsive testimonial card grid with reviewer info |
pricing-comparison |
Three-tier pricing table with elevated recommended card |
blog-post-columns |
wp:query-driven 3-column post grid (portrait images) |
team-grid |
Team member profile grid — photo, name, title, bio |
WooCommerce templates:
| Template | Description |
|---|---|
woo-hero |
Two-column hero: text + CTA left, decorative cover right |
woo-ticker |
Server-rendered marquee ticker bar (needs render_block filter) |
woo-shop-categories |
CSS bento grid: one large featured card + four smaller cards |
woo-featured-products |
Section header with View All + product-collection 4-col grid |
woo-our-story |
Two-column brand story: monogram watermark left, text + stats right |
woo-testimonials |
Three-column testimonial cards with star ratings and avatar circles |
woo-newsletter |
Full-bleed newsletter signup with decorative eyebrow |
woo-shop-landing |
Store homepage shell that composes sub-patterns in sequence |
woo-cart |
Full-width cart page wrapper (Inserter: false) |
woo-checkout |
Full-width checkout page wrapper (Inserter: false) |
woo-filters-sidebar |
Sticky sidebar: price slider + colour-chip attribute + two checkbox-list attributes |
woo-product-grid |
Filter-aware product-collection grid with sort toolbar + pagination |
8 layout skeletons for rapid page construction:
| Layout | Description |
|---|---|
full-width |
Single column, constrained — simplest starting point |
two-column |
50/50 columns block |
three-column |
Grid with 3 equal groups |
sidebar-left |
Narrow left sidebar (33%) + wide content area (66%) |
sidebar-right |
Wide content area (66%) + narrow right sidebar (33%) |
hero-image-left |
Cover image left + heading, text, CTA right |
hero-image-right |
Heading, text, CTA left + cover image right |
landing-page |
Hero + 3-column features + CTA — no header/footer wrapper |
5 preset color palettes for common business verticals:
| Vertical | Color Scheme |
|---|---|
custom |
Enter your own hex color values |
legal |
Navy blue + gold |
plumbing |
Dark blue + orange |
spa |
Sage green + sand |
food-beverage |
Burgundy + gold |
13 reusable code snippets for common pattern components:
| Snippet | Description |
|---|---|
eyebrow-heading-body.txt |
Eyebrow label + heading + body paragraph |
3col-grid-wrapper.txt |
Responsive 3-column grid wrapper |
stat-item.txt |
Number + label stat card (dark background) |
testimonial-card.txt |
Testimonial with stars, quote, author |
two-button-group.txt |
Primary + outline button pair |
overlay-grid-cover-card.txt |
Portrait cover image card + floating badge (use wp:cover, NOT wp:image) |
valid-cover.txt |
wp:cover with all required attrs: dimRatio, backgroundColor/customGradient, minHeight (root integer) + minHeightUnit |
valid-columns-wp66.txt |
wp:columns without inline gap/margin; isStackedOnMobile:false → is-not-stacked-on-mobile class |
responsive-grid-min-width.txt |
wp:group grid layout with minimumColumnWidth — preferred over wp:columns for 3+ columns |
valid-button-attr-order.txt |
wp:button with className/colors before style; font size via style.typography.fontSize |
valid-fullwidth-section.txt |
alignfull outer group + margin reset (top/bottom:"0" no units) + constrained inner group |
valid-heading-with-preset.txt |
wp:heading with fontSize slug in JSON and matching has-{slug}-font-size utility class in HTML |
Built-in configs ship with the tool:
base— default rules for any FSE themeelayne— Elayne-specific rules (extends base)
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:
.pt-cli/{theme}.json(project directory)config/{theme}.json(tool directory)config/base.json(fallback)
| Rule | Autofixable | Severity |
|---|---|---|
| No hardcoded font sizes (CSS px/rem/em) | No | Error |
| No spacer blocks | No | Error |
| Margin reset on alignfull patterns | No | Error |
Balanced HTML tags (<div>, <ul>, <ol>, <li>, <figure>, etc.) |
No | Error |
Responsive grid for 3+ columns (warn on wp:columns) |
No | Warning |
| No hardcoded media IDs | No | Error |
| Translated strings (HTML tags + alt attributes) | No | Error |
Proper patternName in outermost block metadata |
No | Error |
| No HTML comments between opening tags and block comments | No | Error |
No custom domain emails (use example@example.com) |
No | Error |
No hardcoded external URLs in src attributes |
No | Error |
wp:button root fontSize must use style.typography |
No | Error |
wp:button className must come before style in JSON |
No | Error |
Cover block minHeight must have root-level units |
No | Error |
No empty border side objects {} in block JSON |
No | Error |
wp:buttons must have <div class="wp-block-buttons"> wrapper |
No | Error |
No overflow:hidden as inline style on group blocks |
No | Error |
No opacity as inline style on HTML elements |
No | Error |
Font preset classes match root-level fontSize/fontFamily |
No | Error |
No stale inline blockGap/gap/margin on group/column wrappers |
No | Error |
| Rule | Autofixable | Severity |
|---|---|---|
wp:template-part must have "theme":"elayne" attribute |
No | Error |
patternName prefix must start with elayne/ |
No | Error |
| No emoji icons | No | Warning |
woocommerce/product-title inside product-template must use post-title + __woocommerceNamespace |
No | Error |
WC native blocks must not have __woocommerceNamespace |
No | Error |
woocommerce/product-collection must have query metadata |
No | Error |
woocommerce/product-collection must have <div class="wp-block-woocommerce-product-collection"> wrapper |
No | Error |
woocommerce/product-collection must not have both layout and displayLayout |
No | Error |
| 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 |
- 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
git clone https://github.com/imagewize/pt-cli
cd pt-cli
composer install
bin/pt-cli list
bin/pt-cli check --helpMIT — see LICENSE.