Back to blog
4 min read

Getting Started with Blockly: Building Visual Programming Interfaces

A comprehensive guide to integrating Google's Blockly library into your projects, with real-world examples from my experience building DOST

As someone who has spent over 5 years working with Google’s Blockly library, particularly in building DOST, I’ve seen firsthand how visual programming can make coding accessible to everyone. In this guide, I’ll walk you through getting started with Blockly and share some insights from my experience.

What is Blockly?

Blockly is Google’s library for building visual programming editors. It’s the same technology that powers platforms like Scratch and Code.org. Think of it as LEGO for code - users can drag and drop blocks to create programs without writing traditional code.

Why Use Blockly?

From my experience building DOST, Blockly excels at:

  • Making programming accessible to non-programmers
  • Providing instant visual feedback
  • Eliminating syntax errors
  • Creating domain-specific programming interfaces
  • Building educational tools

Setting Up Your First Blockly Project

Let’s create a simple web page with Blockly integration.

1. Basic Setup

Create a new HTML file:

<!DOCTYPE html>
<html>
  <head>
    <title>My First Blockly Project</title>
    <script src="https://unpkg.com/blockly/blockly.min.js"></script>
    <style>
      #blocklyDiv {
        height: 480px;
        width: 100%;
      }
    </style>
  </head>
  <body>
    <div id="blocklyDiv"></div>
    <button onclick="runCode()">Run Code</button>

    <!-- Toolbox definition -->
    <xml id="toolbox" style="display: none">
      <block type="controls_if"></block>
      <block type="controls_repeat_ext"></block>
      <block type="logic_compare"></block>
      <block type="math_number"></block>
      <block type="math_arithmetic"></block>
      <block type="text"></block>
      <block type="text_print"></block>
    </xml>

    <script>
      // Initialize Blockly
      var workspace = Blockly.inject("blocklyDiv", {
        toolbox: document.getElementById("toolbox"),
        scrollbars: true,
        trashcan: true,
      });

      function runCode() {
        // Generate JavaScript code
        var code = Blockly.JavaScript.workspaceToCode(workspace);
        // Execute the code
        try {
          eval(code);
        } catch (e) {
          console.error(e);
        }
      }
    </script>
  </body>
</html>

2. Creating Custom Blocks

One of the most powerful features of Blockly is the ability to create custom blocks. Here’s an example from my work on DOST:

Blockly.Blocks["send_email"] = {
  init: function () {
    this.appendDummyInput().appendField("Send email");
    this.appendValueInput("TO").setCheck("String").appendField("to");
    this.appendValueInput("SUBJECT").setCheck("String").appendField("subject");
    this.appendValueInput("BODY").setCheck("String").appendField("body");
    this.setPreviousStatement(true, null);
    this.setNextStatement(true, null);
    this.setColour(230);
    this.setTooltip("Send an email with specified details");
  },
};

Blockly.JavaScript["send_email"] = function (block) {
  var to = Blockly.JavaScript.valueToCode(
    block,
    "TO",
    Blockly.JavaScript.ORDER_ATOMIC,
  );
  var subject = Blockly.JavaScript.valueToCode(
    block,
    "SUBJECT",
    Blockly.JavaScript.ORDER_ATOMIC,
  );
  var body = Blockly.JavaScript.valueToCode(
    block,
    "BODY",
    Blockly.JavaScript.ORDER_ATOMIC,
  );

  return `sendEmail(${to}, ${subject}, ${body});\n`;
};

Best Practices from Real-World Experience

Building DOST taught me several important lessons about working with Blockly:

1. Block Design

  • Keep blocks simple and focused
  • Use clear, action-oriented names
  • Provide meaningful tooltips
  • Use color coding for different categories
  • Include validation where possible

2. User Experience

  • Organize blocks into logical categories
  • Provide starter templates
  • Include example workspaces
  • Add undo/redo functionality
  • Implement workspace saving/loading

3. Code Generation

  • Generate clean, readable code
  • Include proper error handling
  • Add comments in generated code
  • Consider platform compatibility
  • Implement proper scoping

Advanced Features

1. Custom Toolbox Categories

const toolbox = {
  kind: "categoryToolbox",
  contents: [
    {
      kind: "category",
      name: "Logic",
      colour: "#5C81A6",
      contents: [
        {
          kind: "block",
          type: "controls_if",
        },
        {
          kind: "block",
          type: "logic_compare",
        },
      ],
    },
    {
      kind: "category",
      name: "Loops",
      colour: "#5CA65C",
      contents: [
        {
          kind: "block",
          type: "controls_repeat_ext",
        },
      ],
    },
  ],
};

2. Block Validation

Blockly.Blocks["validate_email"] = {
  init: function () {
    this.appendValueInput("EMAIL")
      .setCheck("String")
      .appendField("validate email");
    this.setOutput(true, "Boolean");
    this.setColour(160);
  },

  validate: function (newValue) {
    // Simple email validation
    return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(newValue);
  },
};

3. Custom Renderers

const customRenderer = new Blockly.blockRendering.Renderer();
customRenderer.constants.NOTCH_WIDTH = 20;
customRenderer.constants.NOTCH_HEIGHT = 10;

const workspace = Blockly.inject("blocklyDiv", {
  renderer: customRenderer,
  toolbox: toolbox,
});

Real-World Example: DOST Implementation

In DOST, we used Blockly to create a visual automation interface. Here’s a simplified version of how we structured our automation blocks:

// Category definition
const automationCategory = {
  kind: "category",
  name: "Automation",
  colour: "#FF6B6B",
  contents: [
    {
      kind: "block",
      type: "browser_action",
    },
    {
      kind: "block",
      type: "keyboard_action",
    },
    {
      kind: "block",
      type: "mouse_action",
    },
  ],
};

// Custom block definition
Blockly.Blocks["browser_action"] = {
  init: function () {
    this.appendDummyInput()
      .appendField("Browser Action")
      .appendField(
        new Blockly.FieldDropdown([
          ["Open URL", "OPEN"],
          ["Click Element", "CLICK"],
          ["Type Text", "TYPE"],
        ]),
        "ACTION",
      );
    this.appendValueInput("VALUE").setCheck("String");
    this.setPreviousStatement(true, null);
    this.setNextStatement(true, null);
    this.setColour("#FF6B6B");
  },
};

Conclusion

Blockly is an incredibly powerful tool for creating visual programming interfaces. Through my experience with DOST, I’ve seen how it can transform complex programming concepts into intuitive, visual experiences. Whether you’re building educational tools, automation systems, or domain-specific programming interfaces, Blockly provides the foundation you need.

Remember to check out the official Blockly documentation for more detailed information, and feel free to explore DOST to see a real-world implementation of Blockly in action.

Happy coding! 🚀