Protoboardbreadboard for coding
Protoboard screenshot

This project was inspired by breadboards: they are used for both learning, and experimenting, allow for very fast iterations, and tap into our spatial reasoning.

Protoboard is a frontend library built on thi.ng/hdom. There's a single exposed function called createBoard which fills the screen with a grid. Pieces of code can be attached to that grid by supplying a name, position, size, and a function:

import createBoard from "protoboard";

const board = createBoard();
board.start();

board.add("hello world", [0, 0], [2, 2], () => {
  return ["h1", "hello!"];
});

Nodes on the board can hold internal state, which other nodes can react to, forming a computational DAG:

board.add("count every second", [0, 0], [2, 2] (state) => ({
  init: () => {
    // initialize with 0
    if (state.deref() === undefined) {
      state.reset(0);
    }

    handle = setInterval(() => {
      state.swap(count => count + 1);
    }, 1000);
  },

  render: () => {
    return ["div", `counter value: ${state.deref()}`];
  },

  release: () => {
    clearInterval(handle);
  }
}));

board.add("counter times two", [2, 0], [2, 2], ({ nodes }) => {
  return ["div", nodes["count every second"] * 2]
});

Protoboard nodes by design encapsulate code instead of other nodes, compared to some VPLs where even basic math equations have to use blocks and connections.

Combination of the background grid, and a quick way to build DOM elements, allows for adding pieces of documentation, notes, and inspiration images inline on the board, creating a canvas for programming:

mini 0
mini 1

Protoboard isn't without issues though. The need to describe position and size of the node in code seems very clean — everything is defined in the same place, and rendering is a pure function over the input file. I just keep on catching myself trying to move the nodes around and resize them using a mouse. Something I want to try is updating the code file when the nodes are moved or resized.

Another issue grows out of the way that nodes are connected together through global naming. This makes it hard to create reusable pieces of code, and the user is forced to create unnecessary abstractions, like:

const createDebugNode = (pos, size, name) => {
  board.add(`${name} debug`, pos, size, ({ nodes }) => {
    return ["code", JSON.stringify(nodes[name], null, 2)];
  });
}
mini 3
mini 2

I believe that writing code in vertical slices on some form of canvas has a lot of benefits, we just don't have the proper interactions and abstractions discovered yet.

Liveboard

Liveboard is a library built on top of Protoboard, providing a set of high-level functions for live-coding music and visuals. Thanks to hot module reload the functions can be swapped immediately, without the need to refresh the whole page.

Szymon Kaliski © 2020
mailtwittergithubwebring