Szymon Kaliski

  1. Main
  2. Projects
  3. Notes
  4. Music
  5. Bio


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 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.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) {

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

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

  release: () => {

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:

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)];

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.


  1. 2024-04-14Canvas for Programming1
  2. 2023-05-20SDFSheetsA Spreadsheet of Signed Distance Functions1
  3. 2020-12-28End of 20201
  4. 2020-11-12FabFungusArt Installation Inspired by Questions of Digital Life and Cellular Growth1
  5. 2020-07-23LiveboardLive-Coding Music with Protoboard1

472 words published on 2020-07-14let me know what you think