Testing x-ocaml, OCaml notebooks as a WebComponent
20 Jun 2025Can we have OCaml notebooks as pure client-side code? Can these notebooks have rich editor support (highlighting, formatting, types on hover, autocompletion, inline diagnostics, etc.)? Can you take packages from OPAM and use them in these notebooks?
The answer to all of these turns out to be a resounding yes thanks for
x-ocaml. This post is my experiment playing
with x-ocaml
and integrating that into this blog.
The most wonderful thing about programming is that it lets you experiment freely. You can try out an idea, get instant feedback, and learn by doing—much like playing with Lego bricks or sketching on a canvas. The two main courses that I teach at IITM, CS3100 and CS6225, both involve me live-coding during every lecture. However, blogging about OCaml where the code is static and non-interactive always felt a bit unsatisfying.
Enter x-ocaml, which allows for a way to
embed OCaml notebooks into any webpage thanks to WebComponents. All you need to
do is to load some JavaScript in your webpage and you can start embedding code
cells using <x-ocaml>
tag. The snippet below:
<x-ocaml>
print_endline "Hello, world"
</x-ocaml>
renders to:
The code is interpreted in the browser thanks to the OCaml interpreter compiled to JavaScript through the Js_of_ocaml compiler. There is also support for Merlin and OCamlformat in the code editor. Try hovering over the functions and writing some code. You should see inferred types and auto-completion suggestions. It turns out that this solution integrates well with Jekyll, which is what I use for this blog.
Reverse-mode AD using Effects
Js_of_ocaml also supports effect handlers. Here’s the implementation of reverse-mode algorithmic differentiation, implemented using effect handlers running in the browser.
Here are some tests.
Using other libraries
x-ocaml
also supports loading any js_of_ocaml compatible library into the
webpage. Let’s use digestif
.
For any library that you want to export, install the library using opam.
x-ocaml
provide a command-line utility to export the library.
$ x-ocaml --effects digestif.ocaml -o digestif.js
This produces the JavaScript artifact that can be used in the webpage. It may be instructive to look at the source of this post to see how the compiler and the libraries are integrated into this blog post. There is a little script at the top of the file:
<script async
src="{{ '/assets/x-ocaml.js' | absolute_url }}"
src-worker="{{ '/assets/x-ocaml.worker+effects.js' | absolute_url }}"
src-load="{{ '/assets/digestif.js' | absolute_url }}"
></script>
What next?
There is a number of rough edges to x-ocaml
. This is expected since this
project appears to be one of Arthur’s hacking
expeditions (which, as usual, is pushing the state of the art forward).
It would be fun to use this for teaching CS3100 and also other OCaml tutorials. Perhaps even have an interactive version of Real World OCaml book.
Not all OCaml libraries can be compiled to JavaScript. The common reason being
that they may depend on features not available on JavaScript. In writing this
post, I unsuccessfully tried for a long time to get
mirage-cypto
working.
mirage-crypto
has a large C
dependency, which
does not work with Js_of_ocaml. Js_of_ocaml promises to take any opam library
installed on your opam switch and compiles that to JavaScript. However, at that
point, we’re really cross compiling the opam packages installed on your switch to
JavaScript since the installed package may make some assumptions about the
platform that it is supposed to run on. Hence, JavaScript compilation of
arbitrary OCaml packages is unlikely to work in the general case. Unfortunately,
the error was difficult to debug since the failure was at runtime, and was not
apparent in the error messages (at least for me, who has little JavaScript
experience). It would be nice to have the opam packages explicitly say whether
they are JavaScript compatible, and have build tooling that reports errors like
these early.