Creating patterns programmatically for a WordPress theme using blocks is incredibly hard and frustrating for so many reasons. Even AIs struggle – and they have access to so much more than we do, so with the help of GPT 5 and days and days of struggle (back and forth coding) it came up with this. I hope it helps.
1. File Structure
- Each pattern lives in its own PHP file inside
/patterns/
. - File must start with a docblock header:
/**
* Title: My Pattern Title
* Slug: my-theme/my-pattern
* Categories: text, theme
* Description: Short description of the pattern.
*/
2. Block Markup Rules
Canonical Format
- No custom HTML comments like
<!-- Title -->
.
✅ Correct:
<!-- wp:heading -->
<h2 class="wp-block-heading">Example</h2>
<!-- /wp:heading -->
❌ Incorrect:
<!-- Title Section -->
<!-- wp:heading {"level":2} -->
<h2 class="wp-block-heading">
Example
</h2>
<!-- /wp:heading -->
3. Headings
<h2>
is the default heading level. Do not include{"level":2}
.- Explicitly set other levels:
{"level":1}
for<h1>
{"level":3}
for<h3>
, etc.
4. Group & Wrapper Blocks
If the root is a <group>
, include metadata:
"metadata":{
"categories":["text","theme"],
"patternName":"my-theme/my-pattern",
"name":"My Pattern"
}
5. Attributes
- Only include non‑default attributes.
- ✅ Keep
{"fontSize":"large"}
if applied. - ❌ Don’t keep
{"level":2}
or other defaults. - WordPress will normalize defaults away.
6. Comments
- Use only WordPress block comments (
<!-- wp:... -->
/<!-- /wp:... -->
). - Do not add developer notes or section labels inside comments.
7. Testing
- Always test by:
- Importing the pattern into the Block Editor.
- Saving the page.
- Verifying zero recovery warnings in the console.
Summary: Do’s & Don’ts
✅ Do:
- Use correct docblock headers.
- Match canonical output exactly.
- Explicitly set heading levels other than
<h2>
. - Include metadata on root group blocks.
- Keep only non‑default attributes.
❌ Don’t:
- Include
{"level":2}
. - Add extra HTML comments.