# Voilà: turning a Jupyter notebook into a web app with a live kernel behind it

> Voilà serves notebooks as standalone web applications and gives each visitor a dedicated Jupyter kernel, so widget callbacks actually run. It is for notebook authors who want a deployment without rewriting their work as a web app.

**voila-dashboards/voila** — Voilà turns Jupyter notebooks into standalone web applications

- Repository: https://github.com/voila-dashboards/voila
- Website: https://voila.readthedocs.io
- Stars: 5,947 · Forks: 528
- Language: Python
- License: NOASSERTION
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/voila-dashboards-voila

## What Voilà actually solves for notebook authors

A converted notebook is a document. It ships the outputs that existed at conversion time, and any slider, dropdown or map is a picture of a slider. Voilà takes the other route: the notebook stays executable, and the thing served over HTTP is a live session. The README states that each user connecting to the Voilà tornado application gets a dedicated Jupyter kernel which can execute the callbacks to changes in Jupyter interactive widgets.

The audience follows from that. If your analysis already lives in a notebook and its interactivity comes from ipywidgets, bqplot, ipyleaflet or ipympl, Voilà is the shortest path from that file to a URL. The README points to a Voilà Gallery of live dashboards built this way, and notes that most of the examples rely on those widget libraries. If your deliverable is a conventional web application with routing, authentication and a database, the notebook is the wrong container and Voilà will not turn it into the right one.

## The kernel-per-visitor model and what it costs you

The architecture is a tornado application that sits in front of Jupyter's execution machinery. Voilà depends on nbconvert and jupyter_server, per the README, and pyproject.toml pins those dependencies: nbconvert>=6.4.5,<8, jupyter_server>=1.18,<3, jupyter_client>=7.4.4,<9, nbclient>=0.4.0, along with websockets>=9.0. That dependency list is the honest description of the mechanism. Notebooks are rendered through nbconvert's machinery, kernels are started through jupyter_client, and the browser talks to the server over a websocket.

The consequence is a process budget. Every connected user holds a kernel. A dashboard that runs a heavy query on load will run it once per visitor, not once per deploy. There is no shared result cache in this design, and nothing in the README suggests one. For a handful of internal users this is fine. For an open page that might get a traffic spike, it is the first thing that breaks.

Two defaults shape the security posture. The README says Voilà by default disallows execute requests from the front-end, preventing execution of arbitrary code, and that it runs with the strip_sources option, which strips out the input cells from the rendered notebook. The first means the browser cannot ask the kernel to run new code it composed itself. The second means your readers see results, not your code, unless you turn it off.

## Installing Voilà and serving a first notebook

Two install paths are documented. conda-forge via mamba, or PyPI via pip. The pip route also pulls in the JupyterLab preview extension: the README states that starting with JupyterLab 3.0, the extension is automatically installed after installing voila with pip install voila.

```bash
mamba install -c conda-forge voila
```

```bash
pip install voila
```

The preview extension adds a side pane in JupyterLab that renders the current notebook the way Voilà would. If you need it from source, the README gives this command.

```bash
jupyter labextension install @voila-dashboards/jupyterlab-preview
```

To serve a single notebook as an app, pass the filename. To serve a whole directory, run voila with no argument.

```bash
voila bqplot.ipynb
```

The repository's own example notebook needs its environment first, which the README handles like this.

```bash
mamba env update -f .binder/environment.yml
cd notebooks/
voila bqplot.ipynb
```

What you should see is the notebook rendered without its input cells, with widgets live. Port and other flags are not enumerated in the README; it directs you to voila --help for command line options such as specifying an alternate port number. Read that output rather than guessing at flag names.

There is a second deployment shape. Voilà can run as a Jupyter server extension under either the notebook server or jupyter_server.

```bash
jupyter serverextension enable voila
jupyter server extension enable voila
```

After that, the README says the Voilà app is accessible from the base url suffixed with voila.

## Where Voilà is the wrong tool

The strip_sources default is a real constraint, not a cosmetic one. If your notebook is the deliverable (a teaching material, a reproducible analysis, a report where the code is part of the argument), the default render hides exactly the part your readers came for. You can set strip_sources to False, and the README shows a sources example doing so, but then you are publishing code execution paths to whoever opens the page. Neither setting is neutral; pick deliberately.

The kernel-per-user model also rules out a class of use. A page that should be cheap to serve to thousands of anonymous readers, or that should be indexable and cacheable by a CDN, is not what this produces. Each connection is stateful and expensive relative to a static file.

Language is not the limit. The README is explicit that Voilà is built upon Jupyter standard formats and protocols and is agnostic to the programming language of the notebook, and it points to a C++ kernel example using xeus-cpp and xleaflet. The limit is widget support. Interactivity in Voilà comes from Jupyter interactive widgets, so a notebook whose interactivity is a JavaScript chart library called directly from a cell will not become interactive here.

The README does not document rollback, multi-user isolation beyond the kernel boundary, or what happens to a long-running kernel under load. Treat those as unverified.

## Voilà against nbconvert's HTML export and against Panel

The closest comparison is the thing Voilà is built on. nbconvert can already turn a notebook into HTML, and Voilà depends on it. The difference is execution timing. nbconvert's HTML export freezes outputs at conversion time; the resulting file is static and can be hosted anywhere. Voilà defers execution to connection time and keeps a kernel alive afterwards, which is what makes widget callbacks work and what makes hosting heavier. If your notebook has no interactive widgets, the HTML export gives you most of the value with none of the process cost.

Panel takes a different starting point. It is a dashboarding library you write against, with its own component model, rather than a server that renders an existing notebook. That means more control over layout and server-side behaviour, and a rewrite of anything you already have in notebook form. Voilà's pitch is precisely that no rewrite is needed: the notebook is the application. If you have already invested in a notebook and its widget stack, that is the argument for Voilà. If you are starting from scratch and want a dashboard framework, the notebook-as-artifact constraint buys you nothing.

## Release cadence, licence and upgrade surface

The most recent release listed is v0.5.13 on 2026-09-04, following v0.5.12 on 2026-04-22 and v0.5.11 on 2025-08-25. The last push to the repository was on 2026-09-07. The repository is not archived. That is a maintained project with a patch-level cadence rather than a fast-moving one, and the version numbers staying in the 0.5.x line tells you the maintainers are not promising API stability by version number alone.

The upgrade surface is wider than a pure Python package because Voilà is also a JupyterLab extension. The repository is a yarn workspace with packages/ and lerna.json, and pyproject.toml lists jupyterlab==4.5.10 in its build requirements. Python support starts at 3.10 and the classifiers go up to 3.14. When you upgrade, you are moving a Python package, a prebuilt JupyterLab extension and a set of pinned Jupyter dependencies together. Check the CHANGELOG.md in the repository before bumping, since the README does not carry upgrade notes.

On licensing: the README says the software is licensed under the BSD-3-Clause license, and package.json carries "license": "BSD-3-Clause". The repository metadata reports the licence as NOASSERTION, which is a metadata-matching artifact rather than a different licence. pyproject.toml declares the licence by file reference, pointing at LICENSE, which is likely why automated detection does not resolve a standard identifier. Read LICENSE and the licences of your widget libraries before redistributing; that is a question for your own counsel, not for this article.

## Conclusion

Adopt Voilà if your deliverable already exists as a notebook with ipywidgets and you want a URL that runs it without a rewrite. Skip it if you need a static, cacheable page, or if you cannot afford a kernel process per concurrent visitor. Before committing, verify three things against your own notebook: that every widget library it imports has a JupyterLab 4 prebuilt extension, that the default strip_sources behaviour matches what you want to expose, and that your jupyter_server version falls inside the >=1.18,<3 range that pyproject.toml pins.

## FAQ

### How do I install Voilà in a Jupyter notebook environment?

Install the package with mamba install -c conda-forge voila or pip install voila. With pip on JupyterLab 3.0 or later, the JupyterLab preview extension is installed automatically, which adds a Voilà preview side pane. You can also enable it as a server extension with jupyter server extension enable voila.

### How do I use Voilà with a Jupyter notebook?

Run voila followed by the notebook filename, for example voila bqplot.ipynb, to serve that notebook as a standalone app. Running voila with no argument serves a directory of notebooks. The notebook is rendered with input cells stripped by default and with live widgets backed by a kernel.

### How do I install Voilà?

The README gives two routes: mamba install -c conda-forge voila from conda-forge, or pip install voila from PyPI. Installing from source for the JupyterLab preview extension uses jupyter labextension install @voila-dashboards/jupyterlab-preview.

### What is Voilà in the Jupyter context?

Voilà is a tornado application that turns Jupyter notebooks into standalone web applications, with each connecting user getting a dedicated Jupyter kernel that can execute callbacks from interactive widgets. It depends on nbconvert and jupyter_server.

## Sources

- [Issues](https://github.com/voila-dashboards/voila/issues)
- [Project website](https://voila.readthedocs.io)
- [README](https://github.com/voila-dashboards/voila/blob/main/README.md)
- [Releases](https://github.com/voila-dashboards/voila/releases)
- [voila-dashboards/voila on GitHub](https://github.com/voila-dashboards/voila)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/voila-dashboards-voila
