[ANN] Bonito.jl

Bonito has been on a journey from being a pretty neglected prototype to something offering similar functionality to established libraries like Shiny/Dash/Streamlit.

It is kind of funny, but I don’t think I’ve ever officially announced Bonito.jl since its creation in 2019, because I’ve never really been happy with it!
Years of small polish and additions finally pushed it over the threshold and I’m happy to announce it :slight_smile:

Key features:

  • Reactive & Interactive: Built on Observables.jl for automatic UI updates when data changes, sending only the minimal amount of data via a fast binary serialization protocol
  • Rich Component Library: Buttons, sliders, tables, code editors, and easy custom widget creation
  • Seamless Plotting: Deep integration with WGLMakie, plus support for Plotly, Gadfly, and anything else supporting the Julia display system
  • Deploy Anywhere: Works in VSCode, Jupyter, Pluto, web servers, or export to static HTML
  • JavaScript When You Need It: Easy ES6 module integration and JavaScript execution
  • Pure Julia Development: Write your entire application in Julia, with optional JavaScript for client-side rendering
  • Extensible Handlers: Wrap and compose handlers for authentication, logging, static files, and custom middleware
  • Use Any Existing JS/CSS/HTML: Bonito provides no opinionated styling by default. Combined with straightforward external dependency integration, this gives you complete access to the entire JS/CSS/HTML ecosystem from within Julia.

Read more in the full blog post: https://makie.org/website/blogposts/bonito

NetworkInspector with Bonito

74 Likes

Awesome :slight_smile: Just curious. Are there thoughts to substitute Observables with the ComputeGraph in Bonito.jl as well, or it doesn’t make sense ?

3 Likes

Not really.
We might not have done a great job communicating this, but Observables is not deprecated and still has very good use cases.
The worst problem of Observables is multi input multi output scenarios, which I at least dont have a lot in Bonito right now - but happens a TON across the Makie internals.
I’m sure there could be a use for Bonito as well and if that ever becomes important we can look into integrating it.

1 Like

Very cool, great work! I am already a happy user of Bonito.jl.

Just curious but would it now be possible to host interactive (note)books on web pages, like for example TU Delft Linear Algebra - Interactive ? (so without running any server side process)

2 Likes

As long as we can’t compile Julia to WASM, any “static” interactivity needs to happen in Javascript, or needs to get its states from a file.
If the framework for the linked course is a JS library, you could also use that with Bonito.jl, and there shouldn’t be any difference to using it from anywhere else.
See: wrapping JS libraries

If you want to use WGLMakie, you’d need to implement the interactivity with Javascript, which will be relatively time consuming.
I want to improve the interactivity of WGLMakie for “static” applications, but not sure when I will have funding and time for it.

1 Like

Hi, is it possible to integrate Bonito.jl into a Julia backend web server based on Oxygen.jl? Currently, I call CairoMakie to render an SVG which then displayed in the frontend with API. But it is non-interactive.

Looks great! Is there a simple example somewhere of using Bonito to make an Interact.jl style plot with e.g. sliders? I tried the below in VSCode, but got an error:

using Bonito, Observables
using GLMakie

app = App() do

    f_slider = Bonito.Slider(LinRange(-10, 10, 101))
    θ_slider = Bonito.Slider(LinRange(-10, 10, 101))
    
    t = range(-5, 5, length=101)
    signal = map(f_slider.value, θ_slider.value) do f, θ
        return @. sin(2π*f*t + θ)
    end

    fig = lines(t, signal)

    DOM.div(f_slider, θ_slider, fig)
end

You need to use WGLMakie (not GLMakie)!
I also added autolimits! to the code, since the limits change massively between slider values:

using Bonito, Observables
using WGLMakie

app = App() do

    f_slider = Bonito.Slider(LinRange(-10, 10, 101))
    θ_slider = Bonito.Slider(LinRange(-10, 10, 101))
    
    t = range(-5, 5, length=101)
    signal = map(f_slider.value, θ_slider.value) do f, θ
        return @. sin(2π*f*t + θ)
    end

    fig, ax, pl = lines(t, signal)
    on(signal) do s 
        autolimits!(ax)
    end
    DOM.div(f_slider, θ_slider, fig)
end
1 Like

Btw, BonitoBook brought back @manipulate from Interact implemented with Bonito:

5 Likes

Yes, thats supported, thanks to some really nice work by @frankier :

I personally would stick with one framework though :wink:

1 Like

What do you mean by one framework? You can check my app at https://app.yxliu.group. I am not familiar with web developing, the whole site is built with Copilot+GPT5 Codex :smiley:

1 Like