Custom Blocks
Barebones supports custom WordPress blocks using block.json, ACF fields, PHP render templates, and block-specific assets. Block setup lives primarily in includes/blocks.php.
Block category
Barebones adds a custom block category called Custom Blocks. You can define your own categories in order to organise blocks by purpose or type. You can define a category within each block's block.json.
add_filter( 'block_categories_all', function ( $categories ) {
$categories[] = [
'slug' => 'custom-blocks',
'title' => 'Custom Blocks'
];
return $categories;
});"category": "custom-blocks"Block directory
Each block lives in its own directory inside blocks/.
blocks/split-content/
├── block.json
├── split-content.php
├── split-content.scss
├── split-content.js
└── preview.jpgUse the same kebab-case name for the directory, PHP file, Sass file, JavaScript file, and compiled assets.
Block registration
Barebones automatically registers blocks by scanning for block.json files. A new block does not need to be manually registered if it follows the expected structure.
function bb_register_blocks() {
$blocks = glob( get_stylesheet_directory() . '/blocks/*/block.json' );
if ( $blocks ) {
foreach ( $blocks as $block ) {
register_block_type( $block );
}
}
}
add_action( 'init', 'bb_register_blocks' );Block namespace
Custom blocks should use the custom-blocks/ namespace. This namespace is used by the editor restriction logic to hide any default WordPress blocks when creating a project that exclusively uses custom blocks.
"name": "custom-blocks/split-content"/**
* Restrict the block editor to custom blocks
*
* @return void
*/
add_filter('allowed_block_types_all', function ($allowed_blocks, $editor_context) {
// Check if we're in the post editor
if (!empty($editor_context->post)) {
// Get all ACF blocks
$acf_blocks = WP_Block_Type_Registry::get_instance()->get_all_registered();
$acf_block_names = [];
foreach ($acf_blocks as $block_name => $block) {
if (strpos($block_name, 'custom-blocks/') === 0) {
$acf_block_names[] = $block_name;
}
}
return $acf_block_names;
}
return $allowed_blocks;
}, 10, 2);ACF render templates
Blocks use ACF to connect block.json to a PHP render template. The render template lives inside the block directory. It can use normal ACF functions.
"acf": {
"mode": "preview",
"renderTemplate": "split-content.php"
}$content = get_field( 'content' );
$image = get_field( 'image' );
$alignment = get_field( 'content_alignment' );Block assets
Block styles and scripts are referenced from block.json.
"style": ["file:../../css/blocks/split-content.css"],
"viewScript": ["file:../../js/blocks/split-content.js"]The source files live beside the block.
- blocks/split-content/split-content.scss
- blocks/split-content/split-content.js
Vite compiles these into the paths referenced by block.json.
Asset versioning
Block assets are versioned with the same file-based approach as global assets.
Barebones filters theme style and script URLs and adds the file modification time as the version.
add_filter( 'style_loader_src', 'bb_block_asset_versioning', 10, 2 );
add_filter( 'script_loader_src', 'bb_block_asset_versioning', 10, 2 );Inline styles
Barebones prevents WordPress from inlining block styles. This encourages WordPress to load the compiled CSS files instead.
add_filter( 'styles_inline_size_limit', '__return_zero' );Preview images
Blocks can define a static preview image in block.json.
"example": {
"attributes": {
"data": {
"preview": "blocks/split-content/preview.jpg"
}
}
}Each block then renders the preview image using bb_block_preview_image_src() when it detects that the block is being loaded in the 'Add Block' editor preview.
<?php if (bb_is_block_preview($block)): ?>
<div class="block-preview"><img src="<?php echo bb_block_preview_image_src($block); ?>" /></div>
<?php else: ?>