The easiest way to develop and release Gutenberg blocks (components) for WordPress

Overview

Contents

Install

npm install gutenblock -g

This is a Gutenberg plugin creator + reusable inspector components with hot loading and code splits built in.

Quickstart

If you have never done WordPress development, getting started couldn't be easier.

When you add docker on the end of the watch command, it will bring up WordPress for you. Simply create an account, install the Gutenberg plugin, and activate the blocks plugin. You're all set.

Comparison with other tooling

Currently, there is only one tool out there to help create blocks (that I have found so far). It's called Create Guten Block. This library was inspired by it. I've added what I consider to be good defaults that everyone would want when creating blocks. These features are not included in other libraries by default:

  • Auto Block registration
  • Helper utlities
  • Automatic code splitting
  • Hot reloading (without page reload)
  • Custom webpack config without ejection

Auto Block registration

No need to call registerBlockType for WordPress. Our loader does this for you.

Helper utilities

Currently, when editing things in gutenberg you make components like this:

const { RichText } = wp.editor;

export default ({ setAttributes, attributes }) => (
  <div>
    <RichText
      tagName="h1"
      value={attributes.title}
      placeholder="Title"
      onChange={title => setAttributes({ title })}
    />
  </div>
);

With Gutenblock, we created a higher order context that is loaded into all edit components. This means you can import our abstracted inputs:

import { RichText } from 'gutenblock-controls';

const Edit = () => (
  <div>
    <RichText name="description" />
  </div>
);

We've included a Select MediaSelect Input Inspector Repeat and other form fields to help you build blocks faster. A repeat component will handle the hard work of letting users add infinite items to an array of form fields, replacing items, and deleting them.

The name field is the key in your gutenberg attributes defined in block.js. You can create your own inputs that connect and get access to setAttributes and attributes, no longer needing to pass them all over in your components. See the example

Code splitting

If you have many blocks, you don't want Gutenberg to load all of that JS when it initializes. With this plugin, your edit blocks will only be loaded in once they are dragged out to the canvas.

Hot reloading

Every edit block is hooked into react-hot-loader with our loader so that updates won't need a full page load. Full reloads can make development much slower when Gutenberg has a lot of content on the page at once.

Custom Webpack

Add a gutenblock.config.js file in your blocks folder. It looks like this:

const path = require('path');

module.exports = webpack => ({
  //customize gutenblock options if needed
  gutenblock: {
    devHost: 'localhost',
    devPort: 8080,
    //build asset output path relative to the plugin directory
    outputPath: '/test',
    //when building the plugin, gutenblock will default to the folder name inside wp-content, if you have a different wp-content folder you can change it here
    publicPath: `/app/plugins/blocks/test/`,
  },
  resolve: {
    alias: {
      shared: path.resolve(__dirname, '../src/shared'),
    },
  },
  plugins: [new webpack.EnvironmentPlugin(['NODE_ENV'])],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [require.resolve('style-loader'), require.resolve('css-loader')],
      },
    ],
  },
});

The configuration is the exact same as webpack with one extra piece: pass babelOptions with plugins and presets like a babelrc has to customize the babel loader.

If you choose to extend the configuration, down the road a future webpack release may require you to make changes and update your configuration. If you do not extend anything, you'll never have to update any configuration in order to upgrade gutenblock!

Future plans

  • Automatic i18n
  • Complicated examples (tabs component, loading in data from WordPress)
  • Test coverage
  • Batch updates when updating nested tabs that cause lots of rerenders in Gutenberg

Usage

gutenblock init will scaffold out a WordPress plugin for you.

gutenblock watch inside the folder will start development mode. Copy the blocks folder into your plugins directory, or use docker

gutenblock build production build the plugin. After, edit line 35 of yourplugin/src/init.php to point to the production assets. All set to publish!

Creating a block

Inside src you will create blocks matching the example one.

All blocks need a block.js and edit.js.

./src/paragraph/block.js

//Optionally use a save block for static rendering on the WordPress frontend

import Save from './save';

const Block = {
  title: 'Paragraph',
  icon: 'shield-alt',
  category: 'common',
  attributes: {
    body: {
      type: 'string',
    },
  },
  save: Save,
};

./src/paragraph/edit.js

import { RichText } from 'gutenblock-controls';

const Edit = () => (
  <RichText tagName="p" name="body" style={{ color: 'black' }} />
);

./src/paragraph/save.js

export default ({ attributes }) => <p>{attributes.body}</p>;

Side note: We don't use save blocks at Crossfield. This is because we fetch WordPress pages and posts via the api and render the blocks using a custom react frontend. Sadly, if you use save blocks, they will not be code split. This is a limitation of the gutenberg editor not supporting awaiting to render the save method.

No registering blocks, importing them into a root folder. It's all done for you.

Now we can run gutenblock watch inside our plugin folder. Inside WordPress the components will hot reload as you edit, thanks to react-hot-loader

You can read more about the Block API

Comments
  •  Repeat Field doesn't seem to work inside editor

    Repeat Field doesn't seem to work inside editor

    Repeat works great in the example file using the inspector panel but doesn't seem to work in the editor.

    Am I missing something?

    Block.js

    const Block = {
        title: 'Repeat1',
        icon: 'shield-alt',
        category: 'common',
        attributes: {
            notes: {
                type: 'array',
                default: [{ title: "one", sub: "two" }],
            },
        }
    };
    

    Edit.js

    
    import { Input, Repeat } from 'gutenblock-controls';
    
    const Edit = ({ attributes }) => {
      return (<Repeat title="Notes" max="50" addNew="Add Field" attribute="notes">
        {attributes.notes.map(tab => {
          return <Input name="title" />
        })}
      </Repeat>)
    
    };
    

    Screen Capture

    screenflow

    opened by timarney 9
  • Uncaught Error: only one instance of @babel/polyfill is allowed

    Uncaught Error: only one instance of @babel/polyfill is allowed

    Hey, I've not been able to get this up and running. With both the gutenblock watch and gutenblock build I get:

    index.js:8 Uncaught Error: only one instance of @babel/polyfill is allowed
        at Object.eval (index.js:8)
        at eval (index.js:12)
        at Object.../node_modules/@babel/polyfill/lib/index.js (main.js?ver=4.9.5:1253)
        at __webpack_require__ (main.js?ver=4.9.5:753)
        at fn (main.js?ver=4.9.5:122)
        at eval (client:2)
        at Object.1 (main.js?ver=4.9.5:5093)
        at __webpack_require__ (main.js?ver=4.9.5:753)
        at main.js?ver=4.9.5:873
        at main.js?ver=4.9.5:876
    

    Thoughts?

    opened by jasonbahl 9
  • Missing loader?

    Missing loader?

    This is by far the best option or building blocks I have come across. I like the features but can't get it to work.

    During watch I get the error

    WARNING in ./src/notes/block.js 34:19
    Module parse failed: Unexpected token (34:19)
    You may need an appropriate loader to handle this file type.
    | Block.edit = function (props) {
    |     return wp.element.createElement(_gutenblockControls.Import, _extends({}, props, { load: function load() {
    >             return import('./edit');
    |         } }));
    | };
     @ ./src sync block.js$ ./notes/block.js
     @ ./index.js
     @ multi ././index.js
    

    I get the same when I build and I have not edited any files yet its a stock install.

    I have run npm install so all dependencies are there.

    Any ideas?

    opened by pippaink 7
  • InspectorControls

    InspectorControls

    Looks like InspectorControls is now under wp.editor . Not sure when that changed.

    wp.editor.InspectorControls
    

    Breaks:

    const { InspectorControls } = wp.blocks;
    
    opened by timarney 7
  • MySql error on starting Docker

    MySql error on starting Docker

    When running gutenblock watch docker I get the following error and cant seem to find a solution.

    wordpress_1 | Warning: mysqli::__construct(): The server requested authentication method unknown to the client [caching_sha2_password] in Standard input code on line 22 wordpress_1 | wordpress_1 | Warning: mysqli::__construct(): (HY000/2054): The server requested authentication method unknown to the client in Standard input code on line 22

    I'm on osx High sierra. Any idea?

    opened by kazlan 4
  • How to translate strings with wp.i18n

    How to translate strings with wp.i18n

    I've read in the readme that you are working on an automated translation system with i18n but what about current situation? How can i manage I18n translation in gutenblock? Even a manual and slow way would be good to go

    opened by StefanoMarchesi 2
  • Repeat - Delete Button -> Add a class for styling

    Repeat - Delete Button -> Add a class for styling

    Would be nice to have a classname to hook onto so the Delete button can be styled

    Example custom styled:

    screen shot 2018-05-08 at 7 55 50 am

    Delete Button in this src code: https://github.com/crossfield/gutenblock/blob/master/controls/src/repeat/index.js

    <div className="whatever-you-want-call-it" onClick={() => this.delete(index, onChange)}>Delete item</div>
    
    opened by timarney 2
  • Use with npx?

    Use with npx?

    First, thanks for working on this. Looks like a great project that will be super useful!

    Lately I've been using npx to run scripts instead of installing globally. I tried with this (npx gutenblock init), and it didn't work. I did install globally and run and it's working.

    Not sure what it takes to work with npx but would be cool if it worked.

    opened by jasonbahl 2
  • Gutenburg 4.x support

    Gutenburg 4.x support

    Just getting back to updating some components I built on top of gutenblock controls. Looks like things break at the 4.x release of Gutenburg. I didn't dig very deep but looks like an issue with importing the Inspector Controls + the Richtext field. Have you run into this?

    opened by timarney 1
  • Updating plugin in docker WP erases folder and fails

    Updating plugin in docker WP erases folder and fails

    Steps:

    1. Run docker
    2. Go into WP plugins – "an update is available" – update this plugin

    The content of the blocks folder is deleted, and even when creating a new folder, WP is ignoring the plugin.

    This is shown in console:

    ERROR in ./index.js
    Module build failed (from ./loader.js):
    Error: ENOENT: no such file or directory, open '/private/var/www/temp/blocks/index.js'
     @ multi ././index.js main[0]
    ℹ 「wdm」: Failed to compile.
    
    opened by braco 1
  • webpack-serve deprecated

    webpack-serve deprecated

    First off, thanks for gutenblock, it's great :)

    webpack-serve has been deprecated; are there any plans to move to webpack-dev-server? I might be able to help with a PR if need be.

    opened by zgreen 2
  • Child/attribute based repeating inputs

    Child/attribute based repeating inputs

    This would be a big deal if possible:

     const CustomBlock = ({ title }) => <div>{title}</div>
    

    edit.js

            <Repeat>
              <CustomBlock
                 title={<Input name="title" />}
              />
            </Repeat>
    

    save.js

       attributes.thing.map(thing => <CustomBlock title={thing.title} />)
    

    It would mean that you could have repeating custom components and edit them in place. The base component wouldn't need to have any knowledge of Wordpress.

    This is MAJOR missing piece from Gutenberg and it should probably be in core, IMO.

    Am I right in thinking this isn't possible with the current patterns you're using? None of the child iteration / cloning you're doing will work, unfortunately, unless the parent CustomBlock was modified.

    opened by braco 1
  • How to add css or scss?

    How to add css or scss?

    Hi Zack,

    Looking at the examples in this repo I couldn't find any blocks with styles.

    I would like to enqueue some structure styles to my block both on the editor and front-end, how is that be done?

    Thanks in advance.

    opened by diegoversiani 11
  • Add ability to change ports

    Add ability to change ports

    When running the docker watch, I am getting this error ERROR: for wordpress Cannot start service wordpress: driver failed programming external connectivity on endpoint blocks_wordpress_1 (92276f168396b71072f54fc7b359a72669273720199ba52e27ea71be1ac3cd1c): Error starting userland proxy: Bind for 0.0.0.0:80: unexpected error (Failure EADDRINUSE)

    That would indicate that port 80 is in use, which is common. It would be great to have an environment variable for port or to automatically find an open one.

    opened by Shelob9 7
  • WP Admin - Plugin update screen

    WP Admin - Plugin update screen

    Just a heads up -


    Admin says update available - screen shot 2018-05-05 at 7 35 33 pm

    Plugin details shows "Blocks" plugin


    screen shot 2018-05-05 at 7 35 52 pm

    Might want to change the name of the blocks dir.

     ncp(__dirname + '/../../plugin', `${process.cwd()}/blocks`, err => {
    
    opened by timarney 6
Releases(1.0.1)
  • 1.0.1(Oct 12, 2018)

  • 1.0.0(Aug 1, 2018)

    New major version bump due to WP moving some components around inside of the wp global object.

    Only update if you are using Gutenberg 3.4 or higher

    Source code(tar.gz)
    Source code(zip)
  • 0.7.0(Jun 26, 2018)

    Updates gutenblock-controls to 0.6.0. Adds new collapsable tabs:

    image

    <Repeat title="Tab" addNew="Add Tab" attribute="tabs" collapsable>
          <Input name="title" placeholder="Tab Title" />
    
          <Repeat title="Items" addNew="Add Item" attribute="items">
            <Input name="url" placeholder="URL" />
            <MediaSelect name="logo" label="Select logo" />
          </Repeat>
        </Repeat>
    

    Collapse top level repeats!

    Source code(tar.gz)
    Source code(zip)
  • 0.6.7(May 22, 2018)

  • 0.6.5(May 8, 2018)

    Add editor component for injected attributes and change function inside of the editor

    https://github.com/crossfield/gutenblock/blob/master/plugin/src/notes/edit.js

    Source code(tar.gz)
    Source code(zip)
  • 0.6.3(May 8, 2018)

    Refactor repeat component to not use state

    https://github.com/crossfield/gutenblock/pull/9

    https://github.com/crossfield/gutenblock/commit/796477ccafb9946da06589dd4af787f80476245c

    Source code(tar.gz)
    Source code(zip)
  • 0.6.1(May 3, 2018)

  • 0.6.0(Apr 27, 2018)

    Breaking change

    Passes in webpack to gutenblock.config.js:

    module.exports = webpack => ({
      plugins: [new webpack.EnvironmentPlugin(['REACT_APP_API'])],
    })
    

    If you imported webpack yourself to access plugins and other built ins, it would resolve locally which may not be the same webpack version and cause errors.

    Source code(tar.gz)
    Source code(zip)
  • 0.5.2(Apr 27, 2018)

    • Fix bug with not being able to call onDelete inside inputs that are nested in a Repeat https://github.com/crossfield/gutenblock/commit/93d088a9187f4527c70e3f84e6c7fedf0850205b
    Source code(tar.gz)
    Source code(zip)
  • 0.5.1(Apr 24, 2018)

    Eslint

    Added create-react-app's eslint config with minor changes for it to work correctly with this project. Now you will see errors about unused variables and other useful things.

    Simplified Input

    Before, there was RepeatInput and InspectorInput. Now, there's just Input which can be rendered in the inspector, or inside of a repeat:

    import { Inspector, Repeat, Input } from 'gutenblock-controls';
    
    export default () => (
      <Inspector>
        <Input name="title" placeholder="Title" />
    
        <Repeat title="Projects" addNew="Add Project" attribute="projects">
          <Input name="title" />
        </Repeat>
    
      </Inspector>
    );
    

    Add MediaSelect component

    import { Inspector, MediaSelect } from 'gutenblock-controls';
    
    export default () => (
      <Inspector>
        <MediaSelect name="backgroundURL" />
      </Inspector>
    );
    
    

    This will prompt the user to select or upload photos and store the resulting image inside the attributes.

    Add Async select component

    Load in items from an api and store the value on attributes

    import { Inspector, Select } from 'gutenblock-controls';
    
    export default () => (
      <Inspector>
        <Select name="id" loadOptions={async search => {
           let response = await fetch(`/wp-json/wp/v2/posts?search=${search}`);
           let json = await response.json();
           return {
             options: json.map(item => ({ label: item.title.rendered, value: item.id })),
           };
    } />
      </Inspector>
    );
    
    
    Source code(tar.gz)
    Source code(zip)
  • 0.4.1(Apr 23, 2018)

    • Fix docker issue with mysql version
    • Fix plugin registered name in gutenberg
    • Add support for sub categories!

    src/category/component/edit.js

    Nest components inside the source folder for better organization. When WordPress adds custom category registration, I'll make it auto categorize blocks.

    Source code(tar.gz)
    Source code(zip)
  • 0.4.0(Apr 21, 2018)

    Remove babel polyfill by default https://github.com/crossfield/gutenblock/commit/0198244318d2f0113322d78a7414b054e3371fa0

    install @babel/polyfilland import in index.js in your plugin folder if you need it.

    Source code(tar.gz)
    Source code(zip)
  • 0.3.1(Apr 18, 2018)

  • 0.2.4(Apr 17, 2018)

    Add in <Repeat/> component for easily adding unlimited items into your components:

    import { Inspector, Repeat, RepeatInput } from 'gutenblock-controls';
    
    export default () => (
      <Inspector>
        <Repeat title="Tabs" addNew="Add Tab" attribute="tabs">
          <RepeatInput name="title" />
          <Repeat title="Notes" addNew="Add Note" attribute="notes" max={3}>
            <RepeatInput name="heading" />
          </Repeat>
        </Repeat>
      </Inspector>
    );
    
    

    Render this inside your <Edit /> component and see what it does. Log props.attributes inside edit to see the state.

    Make sure block.js has:

    tabs: {
          type: 'array',
          default: [],
        },
    
    Source code(tar.gz)
    Source code(zip)
  • 0.2.3(Apr 16, 2018)

    Custom Webpack / Babel

    Add a gutenblock.config.js file in your blocks folder. It looks like this:

    const path = require('path');
    
    module.exports = {
      resolve: {
        alias: {
          shared: path.resolve(__dirname, '../src/shared'),
        },
      },
      module: {
        rules: [
          {
            test: /\.css$/,
            use: [require.resolve('style-loader'), require.resolve('css-loader')],
          },
        ],
      },
    };
    

    The configuration is the exact same as webpack with one extra piece: pass babelOptions with plugins and presets like a babelrc has to customize the babel loader.

    Instant development

    gutenblock watch docker

    will now spin up wordpress for you, (Install gutenberg, enable plugin, boom) so you can just worry about development! If you have your environment already set, guteblock watch works like normal.

    • Removed separate loader package
    Source code(tar.gz)
    Source code(zip)
  • 0.1.3(Apr 16, 2018)

Owner
Zach Silveira
I like coding.
Zach Silveira
Examples for extending WordPress/Gutenberg with blocks.

Gutenberg Examples Examples for extending Gutenberg with plugins which create blocks. See also: Gutenberg developer documentation Installation Gutenbe

null 1.1k Dec 29, 2022
Query gutenberg blocks with wp-graphql

WPGraphQL Gutenberg Query gutenberg blocks through wp-graphql Usage Docs Join our community through WpGraphQL Slack Install Requires PHP 7.0+ Requires

null 270 Jan 3, 2023
Laravel Blog Package. Easiest way to add a blog to your Laravel website. A package which adds wordpress functionality to your website and is compatible with laravel 8.

Laravel Blog Have you worked with Wordpress? Developers call this package wordpress-like laravel blog. Contact us for any customization: contact@binsh

Binshops 279 Dec 28, 2022
Documents WordPress Classic Editor integration points and their Gutenberg equivalents

Gutenberg Migration Guide This repository documents WordPress Classic Editor customization points and their Gutenberg equivalents (if such exist). Its

Daniel Bachhuber 185 Nov 16, 2022
This WordPress Plugin Boilerplate is meant for you to develop your own plugin on.

WordPress Plugin Boilerplate This plugin boilerplate is meant for you to develop your own plugin on. Support & collaboration Features OOP plugin core

richardev 2 May 10, 2022
📦 A zero-configuration #0CJS developer toolkit for building WordPress Gutenberg block plugins.

create-guten-block is zero configuration dev-toolkit (#0CJS) to develop WordPress Gutenberg blocks in a matter of minutes without configuring React, w

Ahmad Awais ⚡️ 3.1k Dec 23, 2022
The easiest to use WordPress option framework.

Titan Framework The easiest to use WordPress options framework. Titan Framework allows theme and plugin developers to create admin pages, options, met

Gambit Technologies 374 Nov 14, 2022
Gutenberg Custom Fields... wait what?

Gutenberg Custom Fields Gutenberg Custom Fields allows you to control the content of the Gutenberg edit screen by creating pre-filled templates. Navig

Riad Benguella 192 Dec 24, 2022
A plugin to disable the drop cap option in Gutenberg editor paragraph block. This is version 2.

Disable Drop Cap (v2) A plugin to disable drop cap option in the Gutenberg editor block editor paragraph block. Note for WordPress 5.8 With WordPress

Johannes Siipola 4 Jan 4, 2022
Centralized dashboard to monitor various WordPress components, stats and data, including the server.

Centralized dashboard to monitor various WordPress components, stats and data, including the server.

Bowo 17 Sep 19, 2022
WordPress plugin boilerplate using React and Block Editor components.

PluginWP Foundation ?? UNDER DEVELOPMENT ?? This code serves as a starting point for building a WordPress plugin using React and the block editor comp

JR Tashjian 5 Dec 8, 2022
Structured content blocks for WPGraphQL

WPGraphQL Content Blocks (Structured Content) This WPGraphQL plugin returns a WordPress post’s content as a shallow tree of blocks and allows for some

Quartz 72 Oct 3, 2022
A better way to create WordPress themes.

Runway Framework for WordPress Visit the Runway website: RunwayWP.com A better way to create WordPress themes. Runway was built for creating WordPress

Parallelus 214 Nov 18, 2022
Rabbit Framework - A modern way of building WordPress plugins

Rabbit Framework - A modern way of building WordPress plugins. About Rabbit Framework is a modern framework designed to be a solid foundation for your

VeronaLabs 8 Nov 20, 2022
A curated list of Awesome WordPress Theme, Plugins and Framework development Resources and WordPress Communities.

Awesome WordPress A curated list of Awesome WordPress Theme, Plugins and Framework development Resources and WordPress Communities. Inspired by bayand

Dropndot Limited 91 Dec 26, 2022
A WordPress plugin to suspend WordPress sites automagically. Simple and lightweight, no annoying ads and fancy settings.

Suspend WP A WordPress plugin to suspend WordPress sites automagically. Simple and lightweight, no annoying ads and fancy settings. ?? Demo (coming so

Waren Gonzaga 3 Nov 15, 2021
Simple WordPress plugin to learn how to understand WordPress Crons and the Action Scheduler library.

Simple WordPress plugin to learn how to understand WordPress Crons and the Action Scheduler library. Import Jamendo playlists with tracks in WordPress posts.

Pierre Saikali 3 Dec 7, 2022
A custom WordPress nav walker class to fully implement the Twitter Bootstrap 4.0+ navigation style (v3-branch available for Bootstrap 3) in a custom theme using the WordPress built in menu manager.

WP Bootstrap Navwalker This code in the main repo branch is undergoing a big shakeup to bring it in line with recent standards and to merge and test t

WP Bootstrap 3.3k Jan 5, 2023
The Pronamic WordPress Basecone plugin allows you to connect your WordPress installation to Basecone.

Pronamic WordPress Basecone The Pronamic WordPress Basecone plugin allows you to connect your WordPress installation to Basecone. Table of contents Au

Pronamic 1 Oct 19, 2021