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: ?>Triggering Javascript in the Block Preview
When you're writing Javascript that would normally trigger on the load event, you will find that it doesn't fire as expected within the block preview. In this context, we need to wait until the block is rendered by ACF before we trigger the code.
We can do this by hooking onto the window.acf event. The sample code below will fire on load in the frontend and on window.acf within the block preview for a block called gallery.
(function($) {
function initialiseGallery(block) {
// Do something
});
initialiseGallery(document);
if (window.acf) {
window.acf.addAction('render_block_preview/type=gallery', initialiseGallery);
}
})( jQuery );