Skip to content

@jupyter-kit/widgets

Renders application/vnd.jupyter.widget-view+json outputs via @jupyter-widgets/html-manager. Works in two modes:

  • Static (no executor) — hydrates metadata.widgets["application/vnd.jupyter.widget-state+json"] from the notebook. Shows saved values, non-interactive.
  • Live (paired with executor-pyodide) — sliders drive Python callbacks, outputs re-render.

WidgetsPluginOptions

OptionTypeNotes
loader(moduleName: string, moduleVersion: string) => Promise<unknown>Called when a widget references a module outside @jupyter-widgets/{base,controls,output}. Return the module exports containing view/model classes.

Usage

Static

import { Notebook } from '@jupyter-kit/react';
import { createWidgetsPlugin } from '@jupyter-kit/widgets';
<Notebook plugins={[createWidgetsPlugin()]} ipynb={nb} />;

Live (Pyodide)

import { createPyodideExecutor } from '@jupyter-kit/executor-pyodide';
import { createWidgetsPlugin } from '@jupyter-kit/widgets';
<Notebook
executor={createPyodideExecutor({ packages: ['ipywidgets'] })}
plugins={[createWidgetsPlugin()]}
ipynb={nb}
/>;

The executor’s commProvider is auto-detected — no extra wiring.

Bundler config (Vite, Rollup, webpack)

@jupyter-widgets/* ship as ESM that still calls require() at runtime in a few spots — a webpack-era hybrid pattern. This is upstream behaviour, not something @jupyter-kit can normalize from this side — the require() calls live inside the published @jupyter-widgets builds. Modern bundlers don’t inject a CJS shim for ESM by default, so without the right config you’ll see one of these in the browser console:

Uncaught ReferenceError: require is not defined
Uncaught ReferenceError: __webpack_public_path__ is not defined

Vite (and Astro)

// vite.config.ts (or `vite:` block in astro.config)
export default defineConfig({
build: {
commonjsOptions: {
// Rewrites `require()` calls inside ESM-flagged files into static
// imports at build time. Required for @jupyter-widgets/*.
transformMixedEsModules: true,
},
},
define: {
// The widget bundle references `__webpack_public_path__` for chunk
// URLs. Vite has no such global; replace with an empty string.
__webpack_public_path__: '""',
},
});

@jupyter-kit/[email protected]+ already sets globalThis.__webpack_public_path__ = '' at module init as a runtime shim, so the define is belt-and-suspenders for older versions or unusual bundle splits.

webpack

webpack handles both natively — no extra config required. Just install @jupyter-kit/widgets and use the <Notebook> component.

Rollup (without Vite)

@rollup/plugin-commonjs with transformMixedEsModules: true. Pair with @rollup/plugin-replace for __webpack_public_path__: '""'.

Bundle cost

The plugin pulls in a fairly large dependency graph:

PackageMinifiedNotes
@jupyter-widgets/{base,base-manager,controls,html-manager,output}~600 KB – 1 MBThe widget runtime itself
jquery~85 KBPeer of @jupyter-widgets/controls slider widgets
jquery-ui~250 KBTransitive — provides $.ui.{mouse,slider,draggable,...}

Total: ~1.0 – 1.4 MB minified. Everything is dynamic-imported the first time the plugin’s setup() runs, so the initial render path stays light — notebooks without widgets don’t pay any of this cost. The plugin is a separate package on purpose for the same reason.

Limitations

  • Requires @jupyter-kit/executor-pyodide (or any other executor that implements commProvider) for interactivity.
  • The ipywidgets Output widget’s automatic matplotlib capture relies on IPython’s display hooks. We monkey-patch interactive.update to approximate it, so @interact(...) style demos refresh their plot on every slider change. More exotic Output use-cases (multi-widget display, clear_output(wait=True) interleaving) may not match classic-Jupyter behaviour.
  • widget-view outputs referencing a model-id that was never registered (e.g. notebook cached outputs where the original kernel state wasn’t saved) render as a muted [widget — run the cell to render] placeholder.