Skip to main content Skills Marketplace Descubre y explora habilidades de IA creadas por la comunidad.
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Copiar promptMostrar detalles del prompt Un comando directo omite el prompt de revisión. Revisa el origen antes de ejecutarlo.
npx skills add https://github.com/bobmatnyc/claude-mpm-skills --skill wordpress-block-editor-fseEl comando permanece en una sola línea. Desplázate horizontalmente para revisarlo antes de copiarlo.
¿Prefieres una copia local? Descarga los archivos que SkillsMP tiene disponibles ahora.
Descargar Zip Descargando... Ocupaciones relacionadas SOC
Basado en la clasificación ocupacional SOC
Explorador de archivos
2 archivos name wordpress-block-editor-fse description Modern WordPress block development and Full Site Editing with theme.json, block themes, and custom blocks for WordPress 6.7+ user-invocable false disable-model-invocation true version 1.0.0 category development author Claude MPM Team license MIT progressive_disclosure {"entry_point":{"summary":"WordPress 6.7+ block development: FSE with theme.json, custom blocks (block.json + render.php), HTML templates","when_to_use":["Block themes with FSE (WP 6.2+)","Custom Gutenberg blocks","Centralized theme.json styling"],"quick_start":["theme.json for design tokens","block.json + render.php","HTML templates not PHP"]},"references":["theme-json-schema.md","custom-blocks-guide.md","fse-architecture.md","migration-guide.md"]} context_limit 6000 tags ["wordpress","gutenberg","blocks","fse","theme-json","php","react"] requires_tools []
WordPress Block Editor & Full Site Editing
Overview
Full Site Editing (FSE) is production-ready (since WP 6.2) and treats everything as blocks—headers, footers, templates, not just content. Block themes use HTML templates + theme.json instead of PHP files + style.css.
Key Components:
theme.json : Centralized colors, typography, spacing, layout
HTML Templates : Block-based files (index.html, single.html)
Template Parts : Reusable components (header.html, footer.html)
Block Patterns : Pre-designed block layouts
Site Editor : Visual template customization
When to Use:
✅ New themes, consistent design systems, non-technical user customization
❌ Complex server logic, team unfamiliar with blocks, heavy PHP dependencies
Full Site Editing Architecture
Block Themes vs Classic Themes
Block Themes Classic Themes HTML files with blocks PHP files with template tags theme.json + CSS functions.php + style.css Site Editor (visual) Customizer (settings) User edits templates Limited customization
Site Editor Capabilities
Template editing (pages, posts, archives)
Template parts (header/footer variations)
Global styles (colors, typography site-wide)
Pattern library (save/reuse block compositions)
Navigation menus (block-based)
Style variations (alternate design presets)
theme.json Configuration
theme.json v3 (WP 6.7) provides centralized design control. WordPress auto-generates CSS custom properties.
Production Example
{
"$schema" : "https://schemas.wp.org/trunk/theme.json" ,
"version" : 3 ,
"settings" : {
"appearanceTools"
:
true
,
"useRootPaddingAwareAlignments"
:
true
,
"layout"
:
{
"contentSize"
:
"800px"
,
"wideSize"
:
"1200px"
}
,
"color"
:
{
"palette"
:
[
{
"slug"
:
"primary"
,
"color"
:
"#0073aa"
,
"name"
:
"Primary"
}
,
{
"slug"
:
"secondary"
,
"color"
:
"#005177"
,
"name"
:
"Secondary"
}
,
{
"slug"
:
"base"
,
"color"
:
"#ffffff"
,
"name"
:
"Base"
}
,
{
"slug"
:
"contrast"
,
"color"
:
"#000000"
,
"name"
:
"Contrast"
}
]
,
"defaultPalette"
:
false
,
"defaultGradients"
:
false
}
,
"typography"
:
{
"fontFamilies"
:
[
{
"fontFamily"
:
"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif"
,
"slug"
:
"system"
,
"name"
:
"System Font"
}
]
,
"fontSizes"
:
[
{
"slug"
:
"small"
,
"size"
:
"0.875rem"
,
"name"
:
"Small"
}
,
{
"slug"
:
"medium"
,
"size"
:
"1rem"
,
"name"
:
"Medium"
}
,
{
"slug"
:
"large"
,
"size"
:
"1.5rem"
,
"name"
:
"Large"
,
"fluid"
:
{
"min"
:
"1.25rem"
,
"max"
:
"1.5rem"
}
}
]
,
"fontWeight"
:
true
,
"lineHeight"
:
true
}
,
"spacing"
:
{
"units"
:
[
"px"
,
"em"
,
"rem"
,
"vh"
,
"vw"
,
"%"
]
,
"padding"
:
true
,
"margin"
:
true
,
"spacingSizes"
:
[
{
"slug"
:
"30"
,
"size"
:
"0.5rem"
,
"name"
:
"XS"
}
,
{
"slug"
:
"40"
,
"size"
:
"1rem"
,
"name"
:
"S"
}
,
{
"slug"
:
"50"
,
"size"
:
"1.5rem"
,
"name"
:
"M"
}
,
{
"slug"
:
"60"
,
"size"
:
"2rem"
,
"name"
:
"L"
}
]
}
,
"border"
:
{
"radius"
:
true
,
"color"
:
true
,
"width"
:
true
}
}
,
"styles"
:
{
"color"
:
{
"background"
:
"var(--wp--preset--color--base)"
,
"text"
:
"var(--wp--preset--color--contrast)"
}
,
"typography"
:
{
"fontFamily"
:
"var(--wp--preset--font-family--system)"
,
"fontSize"
:
"var(--wp--preset--font-size--medium)"
,
"lineHeight"
:
"1.6"
}
,
"elements"
:
{
"link"
:
{
"color"
:
{
"text"
:
"var(--wp--preset--color--primary)"
}
,
":hover"
:
{
"color"
:
{
"text"
:
"var(--wp--preset--color--secondary)"
}
}
}
,
"h1"
:
{
"typography"
:
{
"fontSize"
:
"var(--wp--preset--font-size--large)"
,
"fontWeight"
:
"700"
}
}
,
"button"
:
{
"color"
:
{
"background"
:
"var(--wp--preset--color--primary)"
,
"text"
:
"var(--wp--preset--color--base)"
}
,
"border"
:
{
"radius"
:
"4px"
}
,
":hover"
:
{
"color"
:
{
"background"
:
"var(--wp--preset--color--secondary)"
}
}
}
}
,
"blocks"
:
{
"core/quote"
:
{
"border"
:
{
"width"
:
"0 0 0 4px"
,
"color"
:
"var(--wp--preset--color--primary)"
}
,
"spacing"
:
{
"padding"
:
{
"left"
:
"var(--wp--preset--spacing--60)"
}
}
}
}
}
,
"customTemplates"
:
[
{
"name"
:
"page-wide"
,
"title"
:
"Full Width Page"
,
"postTypes"
:
[
"page"
]
}
]
}
CSS Custom Properties Auto-Generated
Colors: var(--wp--preset--color--primary)
Fonts: var(--wp--preset--font-family--system)
Sizes: var(--wp--preset--font-size--large)
Spacing: var(--wp--preset--spacing--50)
Fluid Typography Font sizes with fluid: { min, max } auto-scale using clamp():
{
"slug" : "large" ,
"size" : "1.5rem" ,
"fluid" : { "min" : "1.25rem" , "max" : "1.5rem" }
}
Block Theme Architecture
Required Files my-block-theme/
├── style.css # Theme metadata (REQUIRED)
├── theme.json # Settings/styles (REQUIRED)
├── templates/
│ ├── index.html # Fallback (REQUIRED)
│ ├── single.html
│ ├── page.html
│ └── archive.html
├── parts/
│ ├── header.html
│ └── footer.html
├── patterns/ # Block patterns
│ └── hero.php
└── functions.php # Optional setup
style.css Metadata
HTML Template Structure
<div class ="wp-block-group" >
</div >
templates/index.html (with query loop):
<main class ="wp-block-group" >
<div class ="wp-block-query" >
</div >
</main >
Template Parts
<div class ="wp-block-group" >
</div >
Block Patterns <?php
?>
<!-- wp:cover {"url" :"<?php echo esc_url(get_template_directory_uri()); ?>/assets/images/hero.jpg" ,"dimRatio" :50 ,"minHeight" :500 ,"align" :"full" } -->
<div class ="wp -block -cover alignfull ">
<div class ="wp -block -cover__inner -container ">
<!-- wp :heading {"textAlign" :"center" ,"level" :1 ,"fontSize" :"xx-large" } -->
<h1>Welcome to Our Site</h1>
<!-- /wp:heading -->
<!-- wp:buttons {"layout" :{"type" :"flex" ,"justifyContent" :"center" }} -->
<div class ="wp -block -buttons ">
<!-- wp :button -->
<div class ="wp -block -button "><a class ="wp -block -button__link ">Get Started </a ></div >
<!-- /wp :button -->
</div >
<!-- /wp :buttons -->
</div >
</div >
<!-- /wp :cover -->
Register pattern categories:
add_action ('init' , 'register_pattern_categories' );
function register_pattern_categories ( ) {
register_block_pattern_category ('hero' , [
'label' => __ ('Hero Sections' , 'my-theme' )
]);
register_block_pattern_category ('cta' , [
'label' => __ ('Call to Action' , 'my-theme' )
]);
}
Custom Block Development
block.json Metadata (Block API v3) blocks/testimonial/block.json:
{
"$schema" : "https://schemas.wp.org/trunk/block.json" ,
"apiVersion" : 3 ,
"name" : "my-theme/testimonial" ,
"title" : "Testimonial" ,
"category" : "widgets" ,
"icon" : "format-quote" ,
"attributes" : {
"content" : {
"type" : "string" ,
"source" : "html" ,
"selector" : ".testimonial-content"
} ,
"author" : { "type" : "string" , "default" : "" } ,
"role" : { "type" : "string" , "default" : "" } ,
"rating" : { "type" : "number" , "default" : 5 }
} ,
"supports" : {
"html" : false ,
"align" : [ "wide" , "full" ] ,
"color" : { "background" : true , "text" : true } ,
"spacing" : { "padding" : true , "margin" : true }
} ,
"render" : "file:./render.php"
}
Attribute Sources Different ways to extract data from HTML:
"attributes" : {
"title" : {
"type" : "string" ,
"source" : "html" ,
"selector" : "h2"
} ,
"linkUrl" : {
"type" : "string" ,
"source" : "attribute" ,
"selector" : "a" ,
"attribute" : "href"
} ,
"isActive" : {
"type" : "boolean" ,
"default" : false
} ,
"items" : {
"type" : "array" ,
"source" : "query" ,
"selector" : ".item" ,
"query" : {
"text" : { "type" : "string" , "source" : "text" }
}
}
}
Server-Side Rendering (render.php) blocks/testimonial/render.php:
<?php
$content = $attributes ['content' ] ?? '' ;
$author = $attributes ['author' ] ?? '' ;
$role = $attributes ['role' ] ?? '' ;
$rating = absint ($attributes ['rating' ] ?? 5 );
$wrapper_attributes = get_block_wrapper_attributes ([
'class' => 'testimonial-block' ,
]);
?>
<div <?php echo $wrapper_attributes ; ?> >
<blockquote class ="testimonial -content ">
<?php echo wp_kses_post ($content ); ?>
</blockquote >
<?php if ($rating > 0) : ?>
<div class ="testimonial -rating ">
<?php for ($i = 1; $i <= 5; $i ++) : ?>
<span class ="star <?php echo $i <= $rating ? 'filled ' : 'empty '; ?>">
<?php echo $i <= $rating ? '★' : '☆'; ?>
</span >
<?php endfor ; ?>
</div >
<?php endif ; ?>
<?php if ($author || $role ) : ?>
<cite class ="testimonial -author ">
<span class ="author -name "><?php echo esc_html ($author ); ?></span >
<?php if ($role ) : ?>
<span class ="author -role "><?php echo esc_html ($role ); ?></span >
<?php endif ; ?>
</cite >
<?php endif ; ?>
</div >
Client-Side Rendering (React) blocks/testimonial/index.js:
import { registerBlockType } from '@wordpress/blocks' ;
import { useBlockProps, RichText , InspectorControls } from '@wordpress/block-editor' ;
import { PanelBody , RangeControl , TextControl } from '@wordpress/components' ;
import { __ } from '@wordpress/i18n' ;
registerBlockType ('my-theme/testimonial' , {
edit : ({ attributes, setAttributes } ) => {
const { content, author, role, rating } = attributes;
const blockProps = useBlockProps ();
return (
<>
<InspectorControls >
<PanelBody title ={__( 'Settings ', 'my-theme ')}>
<TextControl
label ={__( 'Author ', 'my-theme ')}
value ={author}
onChange ={(v) => setAttributes({ author: v })}
/>
<TextControl
label ={__( 'Role ', 'my-theme ')}
value ={role}
onChange ={(v) => setAttributes({ role: v })}
/>
<RangeControl
label ={__( 'Rating ', 'my-theme ')}
value ={rating}
onChange ={(v) => setAttributes({ rating: v })}
min={1}
max={5}
/>
</PanelBody >
</InspectorControls >
<div {...blockProps }>
<RichText
tagName ="blockquote"
value ={content}
onChange ={(v) => setAttributes({ content: v })}
placeholder={__('Testimonial text...', 'my-theme')}
/>
<div className ="testimonial-rating" >
{[1, 2, 3, 4, 5].map((star) => (
<span
key ={star}
onClick ={() => setAttributes({ rating: star })}
>
{star <= rating ? '★' : '☆'}
</span >
))}
</div >
<cite >
<RichText
tagName ="span"
value ={author}
onChange ={(v) => setAttributes({ author: v })}
placeholder={__('Author', 'my-theme')}
/>
</cite >
</div >
</>
);
},
save : () => null ,
});
Block Registration add_action ('init' , 'register_custom_blocks' );
function register_custom_blocks ( ) {
register_block_type (__DIR__ . '/blocks/testimonial' );
}
InspectorControls (Settings Sidebar) Common controls for block settings:
import {
InspectorControls ,
PanelColorSettings ,
MediaUpload
} from '@wordpress/block-editor' ;
import {
PanelBody ,
SelectControl ,
ToggleControl ,
RangeControl ,
Button
} from '@wordpress/components' ;
<InspectorControls >
<PanelBody title ="Layout" >
<SelectControl
label ="Columns"
value ={columns}
options ={[
{ label: '2 ', value: 2 },
{ label: '3 ', value: 3 },
{ label: '4 ', value: 4 }
]}
onChange ={(v) => setAttributes({ columns: parseInt(v) })}
/>
<ToggleControl
label ="Enable Shadow"
checked ={enableShadow}
onChange ={(v) => setAttributes({ enableShadow: v })}
/>
<RangeControl
label ="Border Radius"
value ={borderRadius}
onChange ={(v) => setAttributes({ borderRadius: v })}
min={0}
max={50}
/>
</PanelBody >
<PanelBody title ="Media" >
<MediaUpload
onSelect ={(media) => setAttributes({ imageUrl: media.url })}
allowedTypes={['image']}
render={({ open }) => (
<Button onClick ={open} variant ="secondary" >
{imageUrl ? 'Change Image' : 'Select Image'}
</Button >
)}
/>
</PanelBody >
<PanelColorSettings
title ="Colors"
colorSettings ={[
{
value: bgColor ,
onChange: (v ) => setAttributes({ bgColor: v }),
label: 'Background'
}
]}
/>
</InspectorControls >
Block Supports Enable WordPress features:
"supports" : {
"html" : false ,
"anchor" : true ,
"align" : [ "wide" , "full" ] ,
"color" : {
"background" : true ,
"text" : true ,
"gradients" : true
} ,
"spacing" : {
"padding" : true ,
"margin" : true ,
"blockGap" : true
} ,
"typography" : {
"fontSize" : true ,
"lineHeight" : true ,
"fontWeight" : true
}
}
Custom Post Types with Block Editor add_action ('init' , 'register_book_cpt' );
function register_book_cpt ( ) {
register_post_type ('book' , [
'labels' => [
'name' => __ ('Books' , 'my-theme' ),
'singular_name' => __ ('Book' , 'my-theme' ),
],
'public' => true ,
'has_archive' => true ,
'supports' => ['title' , 'editor' , 'thumbnail' ],
'show_in_rest' => true , // REQUIRED for block editor
'menu_icon' => 'dashicons-book' ,
'template' => [ // Default blocks
['core/paragraph' , ['placeholder' => 'Book description...' ]],
['core/image' ],
['my-theme/book-details' ],
],
'template_lock' => 'insert' , // Can't add/remove blocks
]);
// Register taxonomy
register_taxonomy(' genre', ' book', [
' labels' => [' name' => __(' Genres', ' my-theme')],
' hierarchical' => true,
' show_in_rest' => true, // REQUIRED
]);
}
Template Locking
false: No restrictions
'all': Cannot modify structure
'insert': Cannot add/remove, can reorder
'contentOnly': Content edits only
Register in theme.json "customTemplates" : [
{
"name" : "single-book" ,
"title" : "Book Template" ,
"postTypes" : [ "book" ]
}
]
Development Workflow
@wordpress/scripts {
"scripts" : {
"start" : "wp-scripts start" ,
"build" : "wp-scripts build"
} ,
"devDependencies" : {
"@wordpress/scripts" : "^27.0.0"
}
}
npm install
npm run start
npm run build
wp-env Setup {
"core" : "WordPress/WordPress#6.7" ,
"phpVersion" : "8.3" ,
"themes" : [ "./my-block-theme" ] ,
"config" : {
"WP_DEBUG" : true ,
"SCRIPT_DEBUG" : true
}
}
npx @wordpress/env start
npx @wordpress/env stop
npx @wordpress/env clean
Migration from Classic Themes
Template Tag to Block Mapping Classic Block Equivalent the_title()<!-- wp:post-title /-->the_content()<!-- wp:post-content /-->the_post_thumbnail()<!-- wp:post-featured-image /-->the_date()<!-- wp:post-date /-->wp_nav_menu()<!-- wp:navigation /-->get_header()<!-- wp:template-part {"slug":"header"} /-->get_footer()<!-- wp:template-part {"slug":"footer"} /-->get_sidebar()<!-- wp:template-part {"slug":"sidebar"} /-->
Migration Steps
Extract design tokens from style.css → theme.json
Convert PHP templates to HTML block templates
Add block support in functions.php:
add_theme_support ('wp-block-styles' );
add_theme_support ('align-wide' );
add_theme_support ('responsive-embeds' );
Test thoroughly with real content
Block Validation WordPress validates block markup against registered block definitions. Invalid blocks show errors in the editor:
Common validation errors:
Attribute type mismatch (string vs number)
Missing required attributes
Incorrect HTML structure
Changed attribute names
const deprecated = [
{
attributes : {
oldName : { type : 'string' }
},
migrate : (attributes ) => ({
newName : attributes.oldName
}),
save : (props ) => {
}
}
];
Performance & Best Practices
Performance ✅ Use server-side rendering (render.php) when possible
✅ Leverage block supports (reduces custom CSS)
✅ Disable unused features: "defaultPalette": false
✅ Use CSS custom properties for consistency
❌ Avoid client-side rendering for static content
❌ Don't override core blocks with !important
Accessibility ✅ Semantic HTML (<header>, <main>, <footer>)
✅ Keyboard navigation for custom blocks
✅ WCAG AA color contrast (4.5:1 minimum)
✅ Alt text for all images
❌ Don't assume FSE = accessible (test required)
Anti-Patterns ❌ Mixing classic and block approaches
❌ Hardcoding colors (use CSS variables)
❌ Reinventing block supports
❌ Skipping accessibility testing
❌ Using get_header() in HTML templates
Related Skills
wordpress-plugin-fundamentals : Hook system, CPTs
react : Block editor components
typescript : Type-safe block development
php-security : Sanitize block attributes
Key Reminders
theme.json is mandatory for block themes
HTML templates replace PHP in FSE
Server-side rendering often better than client-side
Block supports reduce custom code
Accessibility requires testing
Red Flags
More than 5 CSS files → Use theme.json
PHP tags in HTML templates → Use blocks
Client rendering for static content → Use render.php
No keyboard testing → Accessibility issues
Hardcoded values → Use CSS custom properties
WordPress: 6.7+ | PHP: 8.1+ | Tools: @wordpress/scripts, wp-env