Legacy
Last modified:
Coming from version 2? Read about the future of Blockstudio as a standalone plugin.
Registration
Composing your own blocks with Blockstudio is extremely easy. The plugin will look for a blockstudio folder within your currently activated theme. Inside, every .php and .twig file will create a new block by making use of the file headers or register variable.
Examples
Let's imagine the following blocks are registered using Advanced Custom Fields:
blockstudio
The above structure would create 7 different blocks with following block names:
- acf/cta
- acf/news
- acf/button
- acf/button-register
- acf/contact
- acf/contact-newsletter
- acf/contact-newsletter-modern
Unlimited nested folders are allowed.
Every filename can only contain lowercase alphanumeric characters, dashes, underscores and must begin with a letter. The acf namespace is automatically being added by ACF. Metabox would use the meta-box namespace instead.
As you can see, naming your file index.php or index.twig will automatically name the block after the parent folder. Please note that this isn't working in the root folder of your block directory.
blockstudio
-- cta.php
-- index.php
In the example above only one block (cta) will be registered since the index.php lies in the root folder.
Naming collisions
Blockstudio automatically gives your blocks unique names depending on their prefix, file name and how deeply they are nested. Since no files can be named the same in a file system, no two block names will ever be the same.
However, using a combination of an index file inside a folder with the same name as a file in the same directory, there is possibility of two blocks having the same name, in which case the file not inside the folder is being preferred since it will be registered first.
blockstudio
-- my-block
---- index.php
my-block.php
Both blocks have the same name. my-block.php will be registered as a block.
Blockstudio provides two different methods to add metadata to your blocks:
File headers
<?php
// cta.php
/*
Title: Call to Action
Description: Call to action element.
Category: blockstudio
Icon: lightbulb
Mode: preview
SupportsAlign: false
SupportsMode: false
*/
The above is equivalent of this ACF code:
add_action( 'acf/init', 'register_cta_block' );
function register_cta_block() {
if( function_exists( 'acf_register_block_type' ) ) {
register_cta_block( [ (
'name' => 'cta',
'title' => __('Call to Action'),
'description' => __('Call to action element.'),
'category' => 'blockstudio',
'icon' => 'lightbulb',
'mode' => 'preview',
'supports' => [ (
'align' => false,
'mode' => false,
],
] );
}
}
While both of these examples will register a block, nothing is being rendered yet. Instead of relying on callbacks or templates, markup in Blockstudio is being defined in the same file as so:
<?php
// cta.php
/*
Title: Call to Action
Description: Call to action element.
Category: blockstudio
Icon: lightbulb
Mode: preview
SupportsMode: false
SupportsAlign: false
*/
?>
<p>Buy my product!</p>
Below is a full list of possible settings that can be set in the file header.
Please note that some block supports need to be activated in the theme, check the Gutenberg docs for reference.
<?php
/*
Title: Testimonial
Description: Content block for customer testimonials.
Category: marketing
Icon: smiley
IconBackground: #000000
IconForeground: #ffffff
Keywords: testimonial customer content (space-seperated)
Mode: preview
Context: side
Align: full
PostTypes: page post (space-seperated)
Parent: acf/my-block
ApiVersion: 2
SupportsAlign: false or left right full (space-separated)
SupportsAlignText: true|false
SupportsAlignContent: true|false or matrix
SupportsAlignWide: true|false
SupportsAnchor: true|false
SupportsColor: true|false
SupportsColorBackground: true|false
SupportsColorDuotone: true|false
SupportsColorGradients: true|false
SupportsColorLink: true|false
SupportsColorText: true|false
SupportsCustomClassName: true|false
SupportsFullHeight: true|false
SupportsHTML: true|false
SupportsInserter: true|false
SupportsJSX: true|false
SupportsLock: true|false
SupportsMode: true|false
SupportsMultiple: true|false
SupportsReusable: true|false
SupportsSpacingBlockGap: true|false or horizontal vertical (space-separated)
SupportsSpacingMargin: true|false or top right bottom left (space-separated)
SupportsSpacingPadding: true|false or top right bottom left (space-separated)
SupportsTypographyFontSize: true|false
SupportsTypographyLineHeight: true|false
*/
?>
It is possible to add additional metadata via PHP while maintaining the data set
with the file header using the $settings
variable.
<?php
// cta.php
/*
Title: Call to Action
Description: Call to action element.
Category: blockstudio
Icon: lightbulb
Mode: preview
SupportsMode: false
SupportsAlign: false
*/
$settings = [
'text-align' => 'left'
];
?>
<p>Buy my product!</p>
Register variable
Alternatively, it is possible to bypass the file headers completely and register
blocks via the $register
variable:
<?php
$register = [
'title' => 'First Block',
'title' => __( 'First Block' ),
'category' => 'formatting',
'icon' => 'design',
];
?>
<p>My Markup</p>
Metabox
Since version 1.3.0, BS supports Metabox blocks with the same known syntax. Since blocks are registed using the rwmb_meta_boxes filter, following snippet has to be added to the functions.php of your currently active theme:
add_filter( 'rwmb_meta_boxes', function ( $meta_boxes ) {
$blockstudio = Blockstudio\Build::init( [
'dir' => get_template_directory() . 'my-mb-blocks',
'prefix' => 'my-prefix',
'type' => 'mb'
] );
return array_merge( $meta_boxes, $blockstudio );
} );
The snippet above would register all blocks inside the my-mb-blocks folder of your current theme.
Gotchas
Blockstudio works with Advanced Custom Fields and Metabox, however, not all options are available for both plugins, the list above just shows all possible settings. Refer to the documentation of ACF or MB to find out which options are supported for each plugin.
Icons: SVGs will only work if no IconBackground
or IconForeground
is
set. If one of those settings is present in the file headers, a
Dashicons identifier has
to be used.
Fields
Of course, the real usefulness of blocks come from connecting custom fields to them. This way, blocks can be infinitely reused with different settings or texts. While defining fields via the ACF or MB interface is completely fine, Blockstudio includes a handy way to register fields in the block files.
Blockstudio is automatically going to look for a $fields
variable inside your
files and if available, will register those and connect them to the block.
ACF
<?php
// cta.php
/*
Title: Call to Action
Description: Call to action element.
Category: design
Icon: lightbulb
Mode: preview
SupportsAlign: false
SupportsMode: false
*/
$fields = [
[
'key' => 'cta_title_key',
'label' => 'Title',
'name' => 'cta_title',
'type' => 'text',
],
[
'key' => 'cta_text_key',
'label' => 'Text',
'name' => 'cta_text',
'type' => 'textarea',
],
);
?>
<h1><?php the_field( 'cta_title' ) ?: 'Title'; ?></h1>
<p><?php the_field( 'cta_text' ) ?: 'Text'; ?></p>
Metabox
<?php
// cta.php
/*
Title: Call to Action
Description: Call to action element.
Category: design
Icon: lightbulb
Mode: preview
SupportsAlign: false
SupportsMode: false
*/
$fields = [
[
"type" => "text",
"id" => "cta_title",
"name" => "Title",
],
[
"type" => "text",
"id" => "cta_text",
"name" => "Subtitle",
],
];
?>
<h1><?php mb_the_block_field( 'cta_title' ) ?: 'Title'; ?></h1>
<p><?php mb_the_block_field( 'cta_text' ) ?: 'Text'; ?></p>
Previews
Previews make it possible to show the block in the inserter panel on hover. This
feature behaves similar to the field registration and has to be defined in an
$example
variable inside your block file.
ACF
<?php
// cta.php
/*
Title: Call to Action
Description: Call to action element.
Category: design
Icon: lightbulb
Mode: preview
SupportsAlign: false
SupportsMode: false
*/
$fields = [
[
'key' => 'cta_title_key',
'label' => 'Title',
'name' => 'cta_title',
'type' => 'text',
],
[
'key' => 'cta_text_key',
'label' => 'Text',
'name' => 'cta_text',
'type' => 'textarea',
],
);
$example = [
'attributes' => [
'mode' => 'preview',
'data' => [
'cta_title' => "Example title",
'cta_text' => "Example text"
]
]
);
?>
<h1><?php the_field( 'cta_title' ) ?: 'Title'; ?></h1>
<p><?php the_field( 'cta_text' ) ?: 'Text'; ?></p>
Metabox
<?php
// cta.php
/*
Title: Call to Action
Description: Call to action element.
Category: design
Icon: lightbulb
Mode: preview
SupportsAlign: false
SupportsMode: false
*/
$fields = [
[
"type" => "text",
"id" => "cta_title",
"name" => "Title",
],
[
"type" => "text",
"id" => "cta_text",
"name" => "Subtitle",
],
];
$example = [
'cta_title' => "Example title",
'cta_text' => "Example text"
);
?>
<h1><?php mb_the_block_field( 'cta_title' ) ?: 'Title'; ?></h1>
<p><?php mb_the_block_field( 'cta_text' ) ?: 'Text'; ?></p>
Twig
Since version 1.4.0, Blockstudio also supports Twig templates. Please note that Timber is needed for templates written with Twig.
Registration
Same as PHP, all block registration data is being taken from the file header.
Please be aware that Twig templates don't support the $register
or $settings
variable at this stage.
{#
Title: My Block
Description: Some description
Category: content
#}
<p>My Markup</p>
Fields and previews
Similar to PHP, custom fields and examples can be defined in their respectively named variable. Let's create the CTA example from before with Twig:
{#
Title: Call to Action
Description: Call to action element.
Category: blockstudio
Icon: lightbulb
Mode: preview
#}
{# acf #}
{% set fields = [
{
"key" : "cta_title_key",
"label": "Title",
"name" : "cta_title",
"type" : "text"
},
{
"key" : "cta_subtitle_key",
"label": "Subtitle",
"name" : "cta_subtitle",
"type" : "text"
}
]
%}
{# metabox #}
{% set fields = [
{
"id" : "cta_title",
"label": "Title",
"type" : "text"
},
{
"id" : "cta_subtitle",
"label": "Subtitle",
"type" : "text"
}
]
%}
{# acf #}
{% set example = {
"attributes": {
"mode" : "preview",
"data" : {
"cta_title_key": "This is the title",
"cta_subtitle_key": "This is the subtitle"
}
} } %}
{# metabox #}
{% set example = {
"cta_title": "This is the title",
"cta_subtitle": "This is the subtitle"
} %}
<h1>{{ field.cta_title }} </h1>
<h2>{{ field.cta_subtitle }} </h2>
Parameters
All PHP parameters are also available in your Twig templates:
{#
Title: Call to Action
Description: Call to action element.
Category: blockstudio
Icon: lightbulb
#}
The available aligns are {{ block.align }}
{% if is_preview %}
Only show this in the block editor.
{% endif %}
The current post id is: {{ post_id }}
Filters
Defaults
It is possible to set global defaults for all blocks registered with Blockstudio
using the blockstudio/defaults
filter:
add_filter( 'blockstudio/defaults', function () {
return [
'post_types' => [ 'post' ],
];
} );
The code above will limit all Blockstudio blocks to posts. Setting the post type on individual blocks will override the global setting.
Prefix
It may make sense to prefix all blocks if you already have an existing blocks
library in either framework. The blockstudio/prefix
filter does exactly that:
add_filter( 'blockstudio/prefix', function () {
return 'bs';
} );
The code above would convert the block name from acf/my-block to acf/bs-my-block.
Custom paths
Changing the location of the folder that is going to be searched for blocks
might be necessary, for example if you are using a page builder like Oxygen,
which disables the theme altogether. Use the blockstudio/path
filter to do so:
// Custom path within your theme.
add_filter( 'blockstudio/path' , function () {
return get_template_directory() . '/blocks';
} );
// Custom path within a plugin.
add_filter( 'blockstudio/path' , function () {
return plugins_url() . '/my-custom-plugin/blocks';
} );
Check out the minimal starter plugin on GitHub, to see how to register blocks from a plugin.
Multiple instances
If the above options are not enough, it is possible to initiate the
Blockstudio\Build
class on various folders of your choice:
add_action( 'acf/init', function () {
// Blockstudio\Build::init( $args );
Blockstudio\Build::init( [
'dir' => get_template_directory() . 'client-blocks',
'prefix' => 'client',
'type' => 'acf'
] );
} );
Using different prefixes is highly advisable in this case, as it'll make sure that no two block names will be the same.
Excluding folders
Sometimes it makes sense to exclude certain folders from Blockstudio. For example, you could have a place to store all components which are used throughout your blocks.
add_filter( 'blockstudio/exclude', function () {
return [ ( 'components' ) ];
} );
The code above will exclude all files inside folders named components.