Legacy

Last modified:

Arrow Forward Circle

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:

Folder Open

blockstudio

Folder Open
contact
Document
index.php
Document
register.php
Folder Open
newsletter
Document
index.php
Document
modern.php
Folder Open
button
Document
index.php
Document
register.php
Document
cta.php
Document
news.php

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
Arrow Forward Circle

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

        
Alert Circle

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

        
Alert Circle

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

See documentation


                <?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

See documentation


                <?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.