Tip: use the table of contents button in the top right of this README to navigate!
Fast exploratory plotting – Julia wrapper for the Observable Plot library. This is a package for high-performance browser-based exploratory plotting in Julia. It installs super fast (<5 secs precompile). It works in Pluto, and possibly also Jupyter, VS Code, etc.
This is an experiment from January 2025 to wrap the amazing Observable library in Julia through HypertextLiteral.jl. I think the result is really good, the combination works very well! Give it a try, and feel free to contribute and continue the project if you like it!
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Check the notebook
example.jlin this repo!!
The aim of the library is to have API that is super close to the original Observable Plot library. Check out their documentation. Not everything from the original library is implemented yet, so feel free to dig in and add more features if you need them!
The API is very similar to the original Observable Plot library, but there are some differences. You essentially need to translate the original API to ObservablePlotExperiment.jl syntax.
A few examples
using ObservablePlotExperimentdata = rand(100)With the "shorthand syntax" you can super easily make a line plot!
lineY(data)This is actually the same as:
line(enumerate(data))(which is also a shorthand syntax). You can also use dot instead of line here for a scatter plot!
dot(enumerate(data))With the plot function you can combine multiple marks into one plot. See the docs for Plot: https://observablehq.com/plot/features/plots
plot(
lineY(data),
dot(enumerate(data))
)Or:
plot(
(
lineY(data .+ i)
for i in 1:10
)...,
)You can also give options to Marks or Plots. The Julia kwargs get automatically converted to JS data structures with HypertextLiteral.jl, yay!
plot(
# dot(enumerate(data); ),
lineY(data; tip=false, marker=true),
text(enumerate(data);
lineAnchor="bottom",
dy=-6,
filter=peaks,
),
x=(label="index"),
# y=(type="log",),
height=200,
)The package ObservablePlotExperiments thus automatically takes care of converting Julia data structures to JavaScript so that it can be used by obsplots.
But what is totally awesome – you can also stick mini-JS-thingies into your Julia code, which then go JS-Julia-JS! And it just works!
Here is an example from example.jl where I make the same plot in different ways.
dates::Vector{Dates.Date}
vals::Vector{Float64}First way:
cell(zip(dates[1:400], vals[1:400]);
x=@jsl("d => d[0].getUTCDate()"),
y=@jsl("d => d[0].getUTCMonth()"),
fy=@jsl("d => d[0].getUTCFullYear()"),
fill=@jsl("d => d[1]"),
)Second way:
cell(tidyzip(
CO₂=vals[1:400],
month=month.(dates[1:400]),
day=dayofmonth.(dates[1:400]),
year=year.(dates[1:400])
); fill="CO₂", x="day", y="month", fy="year")Here I use the function tidyzip from this package. It works roughly like this:
tidyzip(x=[1,2,3],y=[6,7,8]) ==
[
(x=1, y=6),
(x=2, y=7),
(x=3, y=8),
]Want to learn more how to write a package like this? Take a look at Pluto's JS documentation: https://plutojl.org/en/docs/advanced-widgets/
The source code for this package is actually super easy, take a look! And maybe you want to contribute?





