The following image shows where the talk is in the schedule for Sat 2025-12-06. Solid lines show talks with Q&A via BigBlueButton. Dashed lines show talks with Q&A via IRC or Etherpad.
00:01.120 What are reactive notebooks?
00:49.042 Reactivity demo
02:38.499 Org-Babel
03:21.080 Running the whole buffer
03:51.901 Caching
04:21.760 Computation dependencies
06:04.534 Making this even better
07:29.966 Wrapping up
In Org mode, you can add and execute small snippets of code using
Org-Babel. This lets you have an extremely useful mixed-language notebook like
environment inside Emacs. These days, many notebook systems provide fully
reactive notebooks where changes made in any cell or variable propagate to its
dependents without manual execution. This pattern is very useful for exploratory
data analysis, visualization, and many other use-cases that notebooks are
generally good for.
Unsurprisingly, we can enable such reactivity in Org-Babel without too much
effort. In this talk, I will cover how to do that while also adding certain
other interaction niceties to make full use of the resultant reactivity.
About the speaker:
I am a programmer and machine learning engineer, and I have enjoyed working with
Org-Babel code blocks inside my writings. Other notebooks and platforms have
recently started to adopt fully reactive computation, which is something I have
liked a lot for exploratory analysis. In this talk, I will show how to add
similar reactivity in Org-Babel.
Hello, everyone. My name is Abhinav,and I'm going to talk abouthow to make Org Babel reactive. So reactivity heremeans reactivity in the sense of reactive notebooks.So if you used Org Babel,you might also have used Jupyter notebooks,which are basically notebooks primarily forPython programming,where you have these text and code blocks interleaved,and then you can execute every code block independently,and then you control the order of execution manually,or you can just run the code blocksfrom top to bottom. But with reactive notebooks,what happens is that there's another way of runningwhich is basically by having all thesedependent code blocks automatically getexecuted whenever you make a change.So for example, if you change a variable,everything else that's dependent onthat variable will be executed automatically.I'll show you an example of what that looks like.
Right, here's an example reactive Notebook.So this is called Observable.Observable is this tool made bythe creator of d3.js which isa famous JavaScript charting library. So here, theinterface is very similar to Jupyter Notebook.You basically are having these cellsand each cell could be a text cell, like here,this is a Markdown celland then there are these code blocks.Now each code cell is basically defining a variable.This is important in reactive notebooks becauseeach cell is connected to other cell via this variableusage. So here data is defined,then there is filtered which is definedwhich is dependent on data, and then this plot isdependent on filtered.So now, in a classical notebook, what I will do isif I change something here, let's say from 1 to 2,I will have to run this, and then run this plot block againto make the change be visible.But in a reactive notebook, what happens isI can just change this from some valueto some value, and then execute,and then every descendant is also executed,because that's how the reactivity works.You change this variable,so this should also be changed,because this is dependent on this variable.Now this is really helpfulif you have a very complex and messy notebookwhich is what actually happens in reality.You end up doing an exploratory analysis,and you have these code blocks lying here and there.Then you change somethingand then you have to keep something in your mindthat if I change this, I need to runthese five code blocks againto finally get to the result that I want to see.Stale state causes a lot of issues in Jupyter Notebooks.So this is really good for reactivity, sorry reproducibility,but this is also really good forjust having this explorationthat you're trying to do. For example,you're changing something and it's really easyto just see that change happening in real timein your outcome variables, right?
So I was wondering how to introduce this reactivity in Org Mode.And here's how it will look like.So this is a demo Org Mode file.There are many Org Babel blocks here.So you start from here.Let's say this is a code block. It has a name.And then there's another code block,which is dependent on the previous one,as you can see here, and so on.And then finally, there's a plot here,which is a gnuplot code.And you can see the image here.Now, what happens usually is thatif I change this value from,let's say, 113 to 112, nothing happens on its own right?There's an extra step of execution that I will have to doso I will do that, and then the value is changed.Now the problem is that only this value is changed andif I go down and see the image, nothing will have changed.
So what I can do is basically,a really simple thing is that,a simple trick is to basicallyenable a hook, like, add a hookwhenever you're saving the buffer,you just run the full buffer again,like run all the code blocks automatically.Now if you do that, you can basically make a change somewhereand then you can, you know,see how everything else is changingwhich gives you some sort of reactivity,but there's still a lot of computationthat's being wasted.You might not want to change or run this code block againwhen something down there is changing.
So to counter that, you can actually add caching.So if you add caching to any code block,that code block will only be executed againif that code has changed orthe input variables have changed.But the other problem is thatyou don't want caching to be enabled for a lot of caseswhere the code block is actually dependent onexternal state, like for example,some sort of randomness or time.So caching also is, you know, kind of,it's, like, an important thing to use,but it's probably not giving you the complete answer.
So what we can instead do is basically figure outthe whole computation dependencies here.So let's say if I look at this buffer,here's how all the blocks are connected.So as you can see the plot code blockis dependent on c and then legendpg,and they themselves are dependent on these other nodes.So when I make a change in b, I only want b to runand then c and then plot. I don't want anything else to run.So what I did was I wrote a small minor mode for Org Modewhich does exactly this.So whenever you are in a code blockand you are making a change and then you save it,it will just follow the trail from that code blockto every other descendant which is going to be impacted,and it just runs all of them, and nothing else gets executed.So to see it in action, I will just enable that mode.Yeah, right. So now here, if I change this 113 to 112and I save, this code, this variable gets changed.It's the same value because I did not update it again.And you can also see b also got changedbecause it's just following all the execution order and so on.The plot also got updated.We will be able to see more clearlyonce I change something more substantial.So here's another variable.So I added a small toggle button here,which is again part of the minor mode.So since this is nil, if I toggle it,it will become true. And this variable dictates whetherthe plot will have the legend or not.So if I toggle it to be t, now it's tand you can see that the plot has legend that's visible.If I toggle it back again to nil, the legend is gone.Now this is nice, this...
This is already pretty helpful for mebut what we can do is we can make it even better.So one of the nicer ideasfrom these reactive notebooksis this idea of having an infinite canvaswhere you don't look at the document model,you look at the whole documentas a canvas of multiple connected documents.One good thing that happens there is thatyou can basically have a piece of code somewhereand then piece of codesomewhere very different position in the document,but you can put them together in the canvasand then see them side by side.So here also, let's sayif I want to just have this image shown up at the top,what I can do is like I can pop this out,which opens a child frame, and then I can just go here.This child frame is showing the same image.So there's no change. So if I toggle this variable here,you can see that the image is updated.If I toggle it back to nil, the image, the legend is gone.And you can obviously, you know,you can make a lot of things come up as child frames.This is the same image.So even if you go down to the document,you will see the same image.So yeah, this is what I have right now.I'm definitely looking forward to making it more useful,probably including more kinds of child frames,maybe like making the whole document an infinite canvas.
Alright, so that's the talk.If you're interested in the codebase,here's the homepagefor the project [https://dev.lepisma.xyz/git/ob-rx].So the next steps for me are basicallymaking my workflow easier in matplotlib,which is a Python-based library,and d3.js, which is for JavaScript.For the JS thing, I might have to addthe interactive JS child frames,and I am also looking forward to building somethingwhich can replicate the workof the Observable's infinite canvas,because that's somethingwhich I found really useful in my work withjust JS visualizations.So yeah, happy to take questions on Etherpadand thank you for your time.