Patchwork Notes

Breadboard

Orion Reed

Patchwork is built from aspirationally composable parts — tools, documents, views, etc — but the composition itself is hidden. You see a sidebar, a main editor, a toolbar. You don’t see what connects them, or how to change the connections. The assembly disappears behind a finished-looking application.

A rubric that gets passed around the lab holds that “the machinery of the system should be visible” to users. This aligns with a broader goal shared by many here and beyond: that programming and use should sit on a spectrum, not be fundamentally separate activities with separate toolchains and environments. A system should be modifiable within its normal course of use.

I built two small experiments to probe this. They ended up illustrating two distinct strategies — what I’ll call, borrowing a framing from last year’s Software Substrates workshop, postmodernist and modernist approaches to malleability.

Breadboard: working with what already exists

Patchwork’s interface is built from <patchwork-view> elements — custom elements that each render a tool pointed at a document. Sidebars, main editors, and toolbar items are all <patchwork-view> elements. The frame stitches these together into something that looks like a traditional application. Each <patchwork-view> carries its wiring as HTML attributes: tool-id and doc-url.

Breadboard surfaces this wiring. Activate it and the interface scales back. Gaps open between panes. A floating card appears for each <patchwork-view>, showing its tool ID, its document URL, and — when we can read the account doc — the config field name it came from.

The mechanism is simple: document.querySelectorAll("patchwork-view"). Breadboard doesn’t ask the frame for cooperation. It finds views the same way a browser extension or screen reader would — by reading what’s already public in the DOM. Because the wiring lives in attributes, it works with any frame tool, not just the one it was built alongside.

The cards are editable, too. Change a tool-id and the view swaps. Paste a different doc-url and it switches documents.

The name is suggestive but the analogy is imperfect. On a physical breadboard, components plug into a grid and are connected by jumper wires. Everything is visible; everything is modifiable with minimal effort. Wires are not the only kind of relationship in software — we constantly invent new ones: event listeners, reactive dependencies, shared state, data transforms. Many of these can’t be drawn as lines on a board. And where a physical breadboard is operated piecemeal, one wire at a time, digital systems can build tools that operate on many connections at once, or instrument whole classes of interaction.

Digital systems should aspire to the properties of visibility and editability of physical breadboards, but not the material constraints. In electronics there is a massive casm between prototype materials (breadboards and jumper cables) and finished products (integrated circuits and PCBs). Breadboards and PCBs differ from each other because physics demands it: a circuit reliable enough to ship has to be soldered, but digital systems have no such constraint. There is no reason why something reliable cannot also be flexible. Malleability does not imply fragility.

There is a ceiling, though, to how far this approach gets you today. The frame has centralized control over its own layout state. You can inspect it from outside, but you can’t meaningfully reconfigure it without cooperation. The DOM tells you what’s there, not how to change it.

Space-frame: building something new

Space-frame was motivated by some experiments I was doing with transforms as first-class primitives (e.g. transforming LaTeX to HTML) which required a more flexible layout, so I also used this excuse to try a breadboard-esque system but built from the ground up as its own frame tool, not adversarially interacting with an existing frame tool. Where breadboard reads an existing frame from the outside, space-frame is a frame — one where the layout is a first-class editable object.

You can add panes, drag and resize them, drop documents in. Each mutation is reflected directly in the DOM using the nascent moveBefore() API, so the DOM stays the source of truth for layout state rather than some internal model.

Between panes sit <patchwork-pipe> elements — normally thin, 6px drag targets for resizing. Assign a transform to one, and it reads the document from the previous view in DOM order, runs the transform, and makes the result available downstream. Expand it, and the pipe grows into a full pane showing a live preview of the transformed output.

While the transforms are still a work-in-progress experiment, it was clear that adding layout flexibility in the frame tool, where we have totalizing control over the DOM, enabled more polished and reliable UX than breadboard. I am not convinced this must be true, but exactly what is needed to make the DOM in Patchwork a more first-class material (and if we want to do this at all) is not yet clear.

Two approaches

These experiments sit on opposite ends of an axis.

Breadboard is postmodernist: it works with what exists, extending capabilities rather than replacing them. HTML attributes are already public. The DOM is already queryable. No new primitives needed. It works with any frame, not because of a deliberate API, but because <patchwork-view> needs attributes to render and attributes are public by nature.

Space-frame is modernist: it replaces what exists with something designed to have better properties. The layout is editable, pipes can carry transforms, the DOM is the source of truth. But this requires adoption and buy-in in a way that breadboard does not. You have to use the space-frame tool to get its benefits. Neither approach is obviously correct, and the tension between them is not unique to Patchwork.

Building on the DOM

There’s a nice feeling activating breadboard: the sidebar you’ve used every day, the toolbar buttons, the main editor — they’re all the same <patchwork-view> elements. If you can see it on screen, you can touch it. The gap between using the system and modifying it feels smaller.

This didn’t require building an inspection API. I merely stopped hiding what was already there. Both experiments treat the DOM not as a rendering target but as a substrate with useful properties: public attributes, sibling order, containment. Neither abstracts over the DOM. They work with what’s already in it.

The postmodernist strategy — treating the DOM as material — is low-cost and general, but you run into its limits quickly. Frameworks treat the DOM as a rendering target. Build systems assume a uni-directional flow from source code to deployed artifact. The resulting software is not meant to be modified by its users. React’s virtual DOM, for example, can make DOM-level changes fragile as it assumes unilateral control over the DOM subtree it manages.

How far can you get by treating the DOM as a substrate, before you need to build something new? If malleability does not require fragility, then the gap between production and use is a choice we keep making, not a constraint inherent to software or the web platform.