clay

At the eSpark Hackathon last weekend, I had a great time making interesting new things with my work friends. Koppel and John were quite excited by Markov chains and so we had two different kinds of Markov babblers; one was a Slack bot and one was a Twitter bot. Kairui and Cathleen were interested in analyzing how to optimize selection of the right testing content for students; I saw lots of math on the giant paper notepad and a bunch of exciting work from their corner. Chris, Denis and others dug into building a useful internal tool that exposed them to a lot of interesting web dev patterns. Nathan tackled another interesting internal problem and built a complete new feature for our internal dashboards. Also, we played around with the Oculus Rift DK2. I now understand VR-sickness… the sudden loss of head tracking seemed to cause it consistently.

I built something that I had been itching to try: computable documents. Things like iPython and Gorilla REPL are excellent for experimenting with code and bringing together narrative and programming. But often, such tools have installation requirements or require you to be online or run a special local program. I wanted to try and build a tool to make computable documents that could work offline and run on a modern browser with zero installation requirements. I also wanted it to be extremely easy to save and share.

Here I’ll talk more about what I built: Clay, a computable document creator with zero dependencies that is completely contained within a simple HTML file. The document is the tool is the document!

My experiments started with Web Workers. There are two kinds: Dedicated and Shared. Dedicated web workers can be started in the context of the main page script that runs when you load a web page, but after you start them they run in a different computational context (like a different thread). Neither have access to the DOM, but you can communicate from the main page’s context using simple message sending. Shared web workers are largely similar, except they can communicate with any running web page instead of only the parent, and they also run at a particular port (Dedicated workers can be started without specifying or thinking about ports).

Simplest test of my idea: can I start up a web worker and eval some string that contains some Javascript code, and then return the result? Turns out this was very easy (using a Blob uri trick, I could start a web worker using the contents of a simple script tag), and web workers even have a whole API for handling and reporting errors that happen in the worker. So, I quickly had a non-blocking code execution context that ran on the user’s own computer (no backend to speak of) and also acted like a sandbox.

I expanded this further and added code editing and text editing (using the excellent Lightweight Text Decorator library, which allows me to use text decorators and native text editing but also do syntax highlighting and easy dump-to-file-and-reload-state).

The end result: Clay! Link: https://gnarmis.github.io/clay/.

Clay has zero dependencies, is all in one HTML file that’s around 560 lines of commented code, and can run on a modern browser.

It allows you to write sections of text and Javascript code and also execute the Javascript. You have full access to whatever can be accomplished inside a Dedicated Web Worker (that includes AJAX requests to remote servers). Also, if there are any errors, they get caught and displayed. In addition, every time you execute a unit of code, it can assume a totally fresh state; the dedicated web worker is spun up and used for executing code and then automatically cleaned up after use.

But finally, using the Save button in Chrome, you can immediately dump the current state of the web page and load it later and continue editing/eval’ing code as if nothing happened!

Try it out and let me know what you think! https://gnarmis.github.io/clay/clay.html.