Home

Editorama ⎯ songs of code and canvas

  • September 4, 2024


When I first learned about the existence of online resource sites like codrops, or codepen, and codyhouse and a bunch more back in the day, I was bitten by the bug of writing my own editor for the web. That was somewhere in the 2013-2014 era. I had just got my very first computer, I had bought 2 very fat books to teach myself html, css, and javascript (because interfaces were cumbersome to build with java), and it was the time when you got functional web UI examples by still right clicking and looking at view source in the browser. And if you liked a page, you saved it offline, and then pored over the code to figure out how they were doing that cool effect. But that is a different story for another day.

I always wanted to build like a better web editor, something similar to codepen but with the affordances of storing everything in a single HTML file (the kind Claude made popular with Artifacts) ⎯ yes, I wanted them to be modular enough to be simply swapped between machines as standalone “software files” that can go from computer to computer and still do the job that needed done. Plus, building it with HTML gave you amazing compatibility. It was one of the truest write once, run anywhere paradigm, or so I thought as a 15 year old ⎯ and maybe, that guy wasn’t wrong. And every computer on any device has a browser already, right? Right. This was also the time right before the internet boom happened in India ⎯ Aircel was still a telecom provider you still had to draw out a gigabyte of data allowance last a month. The scarcity of internet made running internet-powered services pretty unreliable, and for us at that time, making fun toys and games and exchanging them with each other or showing them off in the school’s annual science fair was a thing, and pen drives were our trusted sidekicks. Also, the games and tools we made needed to work offline, and learning about localstorage and IndexedDB to add persistence and leaderboards was I feel, the original stimulus that now has condensed int the local-first movement.

An initial prototype for a web-based code editor with the chat controls to steer this codebase stacked on the left ~ 2022

When Anthropic released Claude Artifacts in 2024, and it just allowed you to render the html and just preview it, with none of the bells and whistles that I’d have loved and appreciated, I got really bummed and decided to go ahead and build my own editor ⎯ it was time. It helped that I was already neck deep in handling a different kind of editor back then, and unknowingly, a bunch of decisions from this other tool flowed into what eventually became Popsicle. But to tell you the full story and my tryst with editors, we need to back up a little bit more, all the way back to 2019.

I was neck deep switching time between Python and javascript codebases, and while translating some python functions to do some machine learning voodoo, the frustration of having to write out ⎯ manually so much more js code made me start tinkering with compilers, and while I did not have any concrete ideas by the time I made this proposal video for PyCon India 2019 (did not get accepted 😬), I was hacking together a few ideas to see what we could do to bring these 2 paradigms together.

One of the ideas was to have a custom file format and a custom parser that would separate out python and js blocks and send them to execute using their respective tooling ⎯ sort of a router to direct the code blocks to their separate executions engine and then bring them back together. This question remained unanswered for a couple of weeks while I went on another side quest : what if you had a visual tool/plugin/sidebar that condenses all configurable values in the code file into visual blocks ⎯ and if we can extract the semantic context of why this certain variable is being used, we wanted to condense them into each to toggle, switch, and editable controls.

Chrome’s dev tools does this to a certain extent where I get value suggestions based on the active key 👇

This side quest led to another small prototype that explored this visual rendering of variables alongside their code (with 2-way binding so that the user can update the values from both the actual line of code and the new extracted visual control).

javascript variable visualizer ⎯ derived from python-javascript, the 2 formats that I was trying to make talk with each other.

You can try it out here : JS Variable Visualizer

Happy that my hypothesis was fun and having some dopamine hits playing around with the new toy, I abandoned all of these quests at the prospect of joining my first software engineering role in 2020. Fast forward to March 2020, the pandemic hit and everything shut down and we had to stay indoors (I don’t think all of properly recovered from that fevered dream and even now you think of last year as 2019 but it’s actually 2024 and you go like ‘woah!’).

I came back to the idea of marrying off python and javascript again and it clicked then, that I could simply build a block-based notebook and run python there directly (thank you to the pyodide and webassembly gods for granting us the elixir of running anything in the browser), and to bring them both together so that they “talk” to each other, we maintain a shared variable dictionary and both javascript and python blocks can access and modify those variables. It worked! And then again it clicked with me, “oh, the answer was notebooks all along!”

pj ⎯ derived from python-javascript, the 2 formats that I was trying to make talk with each other.

pj was a really fun nut to crack ⎯ and after spending an ungodly amount of time doomscrolling and contemplating whether I even liked making computer things, I decided/realized that I did. That some of these toys were simply for fun and prototyping problems I was facing with existing tools.

You can try PJ out here : PJ Notebook


The next chapter happens in early 2022 ⎯ large language models are all the rage now. Turns out those matrix multiplication machines end up writing pretty useful code, and if they’re giving me functional, mostly correct (if you’re smart and got small chunks of code generated at a time, provide proper context and probably laying out variables to use, function definitions and other conventions to follow also really helped, and that you could still get GPT-3 to do amazing hitherto unknown things), why aren’t they in my editor anywhere. And I was also making my own tryst with p5.js at the time and I went, well, what if I could use the double slash to write a comment syntax to also mean a prompt (GitHub still had not released Copilot) and that’d give me the relevant p5.js code which runs and shows me the output, and I can keep doing this all day and my tools never usually have a persistent remote databases attached unless absolutely necessary because I am really scared of remote servers and databases. I build a local indexedDB-powered version control system and slapped it on to this p5.js editor that I cheekily christened p6. And it made successive explorations so much fun.

p6 ⎯ a web-based p5.js editor with Gemini-powered autocomplete and local version control, the 2 formats that I was trying to make talk with each other.

You can try out the P6 editor here : P6 Editor


At the same time, I was going on another different tangent of exploring interfaces where the change orchestrator, the material, and the rendering can remain in view at the same time and that led to 3 fun explorations :

  • A vector editor that shows the rendering and the svg code side by side, also with 2-way control binding. That a change in canvas reflects on the code and vice versa ⎯ Vector Editor

  • Figma never really allowed you to export an interaction prototype as a functional thing to be plugged into your codebase, so I built Animator ⎯ import your svg and add states and motion and new positions to that. Having an easier deterministic toggle to actually make functional edits is a superpower, and this specific tool tied back to the exploration of visual controls for dynamic variables embedded in code ⎯ SVG Animator

We now fast forward to 2024 ⎯ GitHub had released Copilot sometime back, we had been swept off our feet by local changes, Replit also released a checkpoints system which was cool and I kept playing with all of these tools for the year and half in between, building toys and games and something I was calling a “model orchestrator”, I came back to another set of gnawing questions regarding how the inadequate the version controls in p6 felt, and there were smarter models coming out all the time, and I kept editing the actual codebase to switch out the models and plug in the next one, and then the next one, and then the next one, until I was spending most of my time updating the model specifications in my prototypes - running constant maintenance instead of exploring new ideas. I was also building my own mental models and primitives. I did not want to keep switching between copilot and claude and then to gemini for debugging and adding new smaller bits and fixing bugs, that gemini has always been traditionally good at.

diffy ⎯ a web-based multi-dimensional version control prototype, helps you see parallel changes implemented by multiple models using your chat messages as the visual checkpoint.

You can try out Diffy here : Diffy


I first set out to simplify the multi-dimensional version control problem. I prototyped diffy ⎯ a chat-based code rendering prototype where every message lead to responses from multiple models, allowing you to see and compare changes in real time. Also, every message itself acts as a version control stamp that you can click at to travel across versions. It was important to map this mechanic as chat becomes one of the foundational primitives to driving open-ended actions that when we talk and eventually and triggers something, in here, a file changes. The issue with the primitive tools that were not really tied to something like git is that while making the thing fades to the background and you don’t really get sense of the tactility of the material, code itself. There’s this whole separate discourse around should designers code and there’s a school of thought that says no and it’s so weird because in no other field of design would you ever discourage the person to master a material by learning to work WITH THE MATERIAL.

So I finally built out an artifact editor that I’d want to use and seamlessly change things. In its early days, Popsicle just allowed you upload an html artifact and only then made edits and changes to it, and I added a version of inspect element and the devtools interface to visually update layouts and pages and merge that data back to the DOM. Popsicle works on the similar principle as codepen, you have a code view and you get a preview that you can switch between. And the chat controls persist on the side along with the version control and other bits and pieces to ensure that you can see the changes in the material.

popsicle ⎯ a web-based prototyping tool with version control and a bunch of tools to manipulate raw code, including LLM-driven pipelines and a raw IDE to physically edit code.

Any modifications in code translates to the preview, and in the preview section, you can leave comments tied to very specific pieces and have agents work on them.

Hovering over a code section gives you a semantic summary of what’s happening, and this continuous building up on semantic index helps you search across the entire semantic sense of the artifact’s code. All AI-triggered changes trigger a checkpoint, and regardless of whether you accept/deny the changes, you can always come back and check the diff of what had happened before considering whether to revert back to that version. Showing the highlighted code diff is helpful to also see and learn how the material responds to your prompt, and it is strangely satisfactory to see the actual end artifact take shape.

A fun tool I built into popsicle is the style transfer flow. It was a stab at figuring that if we have a reference of styles laid out in a functional html page, we can pass that directly to models and they do a pretty good job at translating the code to maintain styles. It was fun to build this one, tweaking and making changes until the style translation worked just right. It uses a fun dropper interaction and you go through this whole process of picking up a style from a list of saved styles and dropping that style on the artifact in the main canvas.

style transfer in popsicle ⎯ using an eyedropper to pick up a style and drop it on the target artifact

Take Popsicle for a spin here : Popsicle


But all of these were tied to a much bigger thesis on how interfaces should adapt to our work.

And here’s where I should confess the thing I danced around for this whole essay : none of this is new. The dream of software you can reach into and reshape is almost as old as personal computing itself, and I’m just one more person in a very long line who caught the bug. Alan Kay and the folks at Xerox PARC imagined Smalltalk and the Dynabook as a metamedium ⎯ not an app you use but a material you mould, a system where even a kid could crack open any part and change how it behaved. Doug Engelbart stood on a stage in 1968 and demoed a machine whose entire reason for existing was to augment the human sitting in front of it, to bend toward them. And for one brief, beautiful window in the late 80s, HyperCard actually shipped this to regular people ⎯ Bill Atkinson handed everyone a way to build their own little stacks of software without ever having to call themselves a programmer, and then it was quietly allowed to die, and a certain kind of person has been mourning it ever since. Emacs is maybe the last one standing from that era that never gave up the ghost : a program that is mostly its own configuration, a thing you spend a whole career molding into the exact shape of you.

There’s a bit from Christopher Alexander I think about a lot here, even though he wasn’t talking about software at all ⎯ his whole A Pattern Language is built on the radical idea that the people who live in a building should be the ones shaping it, not some architect who parachutes in and leaves. In no other design discipline do we take the material away from the person actually using it, and yet software does exactly this, constantly, and calls it a good experience. Which lands us squarely on the question the whole malleable-software conversation keeps circling back to : now that a model can write working code on demand, why are we still trapped inside apps that somebody else already finished for us?

Which brings me, finally, to the actual principle underneath all of these toys ⎯ the thing I only saw clearly somewhere around the tenth prototype. My fundamental belief is that software should “spawn” the pieces you need to finish whatever you were already doing. Not send you off to a menu. Not make you leave and open another app and lose your thread and your train of thought along with it. It should notice the shape of the thing you’re reaching for and just conjure it, right there, in the flow. And this spawning can take a bunch of different forms depending on the work ⎯ but for editing interfaces specifically, I think it looks like floating windows that call in whichever component is needed at exactly the moment it’s needed, and then get out of the way the moment it isn’t. Once you’re holding this idea in your head, imagining workspaces that are genuinely fluid ⎯ that reconfigure themselves around the task instead of forcing the task to squeeze through a fixed layout ⎯ becomes so much easier. The workspace stops being a room you walk into and starts being something closer to water.

The prototype I’d been building to chase this exact tenet is called Sphere, and it’s an exploration of tools within tools ⎯ meta-tools, if you’ll let me be pretentious about it. The idea is that a tool should be able to spawn smaller, purpose-built tools inside itself on demand. Chrome extensions turned out to be a wonderfully weird proving ground for this : can an LLM one-shot a functional, actually-working plugin straight from a single prompt? Sometimes! The honest answer is that the current loop just doesn’t hold together without a decent set of guardrails wrapped around it, and Sphere in its present state is glitchy and very much a hit-or-miss affair ⎯ some spawns come out as little miracles and some come out as complete nonsense and I never quite know which I’m going to get until I run it. But even the misses are instructive, because they show you exactly where the seams of this whole paradigm are still tearing.

If you want to see a grown-up, far-less-glitchy version of this same spirit made real, go play with the Glamorous Toolkit. It’s a “moldable development environment” out of the feenk crew, and its whole philosophy of moldable development ⎯ that you should build a small, custom, throwaway tool for the specific problem sitting in front of you rather than squinting at the same generic ones forever ⎯ is one of the most quietly radical things happening anywhere in this space right now. It’s the clearest existing proof I’ve found that malleable software isn’t just a nostalgia trip for the HyperCard days. Genuinely, go check it out, it’s worth a slow afternoon.

Because that’s the thread running through all of it ⎯ pj and p6 and diffy and Popsicle and Sphere and every abandoned side quest in between. None of them were ever really about python or javascript or p5.js or artifacts. They were all, every single one, small arguments for the same stubborn belief : that the software should bend toward the person, and not the other way around. I’ve spent the better part of a decade making toys to prove a point I could probably have said in one sentence. But you don’t really get to feel a thesis until you’ve built it and watched it break in your hands ⎯ and that, more than anything, is the whole song.