WGLMakie is the web-based backend, which is mostly implemented in Julia right now. WGLMakie uses JSServe to generate the HTML and JavaScript for displaying the plots. On the JavaScript side, we use ThreeJS and WebGL to render the plots. Moving more of the implementation to JavaScript is currently the goal and will give us a better JavaScript API, and more interaction without a running Julia server.


WGLMakie can be considered experimental because the JavaScript API isn't stable yet and the notebook integration isn't perfect yet, but all plot types should work, and therefore all recipes, but there are certain caveats

Missing Backend Features

  • glow & stroke for scatter markers aren't implemented yet

  • lines(...) just creates unconnected linesegments and linestyle isn't supported

Browser Support

  • JSServe now uses the IJulia connection, and therefore can be used even with complex proxy setup without any additional setup

  • reload of the page isn't supported, if you reload, you need to re-execute all cells and make sure that Page() is executed first.

JupyterHub / Jupyterlab / Binder

  • WGLMakie should mostly work with a websocket connection. JSServe tries to infer the proxy setup needed to connect to the julia process. On local jupyterlab instances, this should work without problem, on hosted ones one may need add jupyter-server-proxy. See:

    • https://github.com/MakieOrg/Makie.jl/issues/2464

    • https://github.com/MakieOrg/Makie.jl/issues/2405


  • still uses JSServe's Websocket connection, so needs extra setup for remote servers.

  • reload of the page isn't supported, if you reload, you need to re-execute all cells and make sure that Page() is executed first.

  • static html export not fully working yet


  • VSCode in the browser should work out of the box.

  • Pluto in JuliaHub still has a problem with the websocket connection. So, you will see a plot, but interaction doesn't work.

Browser Support

Some browsers may have only WebGL 1.0, or need extra steps to enable WebGL, but in general, all modern browsers on mobile and desktop should support WebGL 2.0. Safari users may need to enable WebGL, though. If you end up stuck on WebGL 1.0, the main missing feature will be volume & contour(volume).

Activation and screen config

Activate the backend by calling WGLMakie.activate!() with the following options:

WGLMakie.activate!(; screen_config...)

Sets WGLMakie as the currently active backend and also allows to quickly set the screen_config. Note, that the screen_config can also be set permanently via Makie.set_theme!(WGLMakie=(screen_config...,)).

Arguments one can pass via screen_config:

  • framerate = 30: Set framerate (frames per second) to a higher number for smoother animations, or to a lower to use less resources.


You can use JSServe and WGLMakie in Pluto, IJulia, Webpages and Documenter to create interactive apps and dashboards, serve them on live webpages, or export them to static HTML.

This tutorial will run through the different modes and what kind of limitations to expect.


Page() can be used to reset the JSServe state needed for multipage output like it's the case for Documenter or the various notebooks (IJulia/Pluto/etc). Previously, it was necessary to always insert and display the Page call in notebooks, but now the call to Page() is optional and doesn't need to be displayed. What it does is purely reset the state for a new multi-page output, which is usually the case for Documenter, which creates multiple pages in one Julia session, or you can use it to reset the state in notebooks, e.g. after a page reload. Page(exportable=true, offline=true) can be used to force inlining all data & js dependencies, so that everything can be loaded in a single HTML object without a running Julia process. The defaults should already be chosen this way for e.g. Documenter, so this should mostly be used for e.g. Pluto offline export (which is currently not fully supported, but should be soon).

Here is an example of how to use this in Franklin:

using WGLMakie
using JSServe, Markdown
Page(exportable=true, offline=true) # for Franklin, you still need to configure
scatter(1:4, color=1:4)