npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@datalayer/jupyter-embed

v2.0.20

Published

Easily embed Jupyter components (cells, notebooks, terminals, consoles) into any web page

Readme

Datalayer

Become a Sponsor

🪐 🌐 Jupyter Embed

Easily embed Jupyter components (cells, notebooks, terminals, consoles) into any web page.

npm version License: MIT

🚀 Live Demo: jupyter-embed.datalayer.tech

Overview

@datalayer/jupyter-embed allows you to convert any website or blog into an interactive Jupyter-powered learning platform. Simply add a script tag and HTML elements with data attributes to embed:

  • Code Cells - Interactive Python/Julia/R cells with execution
  • Notebooks - Full Jupyter notebooks with all features
  • Terminals - Interactive terminal sessions
  • Consoles - Jupyter console for REPL-style interaction
  • Outputs - Display pre-computed Jupyter outputs

Powered by the full Jupyter ecosystem via @datalayer/jupyter-react.

Minimum HTML Example

Here's a complete, minimal HTML file that embeds an interactive Jupyter cell. Copy this and open it in your browser:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Jupyter Embed - Minimal Example</title>
    <!-- Required for ipywidgets support -->
    <script
      data-jupyter-widgets-cdn="https://cdn.jsdelivr.net/npm/"
      data-jupyter-widgets-cdn-only="true"
    ></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js"></script>
  </head>
  <body>
    <h1>My Interactive Code</h1>

    <!-- Jupyter Cell -->
    <div
      data-jupyter-embed="cell"
      data-jupyter-height="200px"
      data-jupyter-auto-execute="true"
    >
      <code data-jupyter-source-code> print("Hello from Jupyter!") </code>
    </div>

    <!-- Load Jupyter Embed with configuration -->
    <script
      type="module"
      src="https://jupyter-embed.datalayer.tech/jupyter-embed.lazy.js"
      data-jupyter-server-url="https://prod1.datalayer.run/api/jupyter-server"
      data-jupyter-token="60c1661cc408f978c309d04157af55c9588ff9557c9380e4fb50785750703da6"
      data-jupyter-lazy-load="true"
      data-jupyter-auto-start-kernel="true"
    ></script>
  </body>
</html>

Note: The example above uses Datalayer's public demo server. For production use, configure your own Jupyter server.

Quick Start

1. Include the Script

Add the script to your HTML page:

<script src="https://unpkg.com/@datalayer/jupyter-embed/dist/jupyter-embed.js"></script>

2. Configure the Connection

<script type="application/json" data-jupyter-embed-config>
  {
    "serverUrl": "http://localhost:8888",
    "token": "your-jupyter-token",
    "defaultKernel": "python3"
  }
</script>

Or via data attributes on the script tag:

<script
  src="jupyter-embed.js"
  data-server-url="http://localhost:8888"
  data-token="your-token"
></script>

3. Add Embed Elements

<!-- Code Cell -->
<div
  data-jupyter-embed="cell"
  data-jupyter-height="200px"
  data-jupyter-auto-execute="true"
>
  <code data-jupyter-source-code> print("Hello, Jupyter!") </code>
</div>

<!-- Notebook from file -->
<div
  data-jupyter-embed="notebook"
  data-jupyter-path="notebooks/demo.ipynb"
  data-jupyter-height="500px"
></div>

<!-- Terminal -->
<div data-jupyter-embed="terminal" data-jupyter-height="300px"></div>

Installation

CDN (Browser)

<!-- IIFE bundle (adds JupyterEmbed global) -->
<script src="https://unpkg.com/@datalayer/jupyter-embed/dist/jupyter-embed.js"></script>

<!-- ES Module -->
<script type="module">
  import {
    configureJupyterEmbed,
    initJupyterEmbeds,
  } from 'https://unpkg.com/@datalayer/jupyter-embed/dist/jupyter-embed.esm.js';
</script>

ESM Build with Vendor Chunking (Recommended for Production)

For better caching and faster repeat visits, use the chunked ESM build:

<!-- ESM build with automatic chunk loading -->
<script
  type="module"
  src="https://cdn.example.com/jupyter-embed.esm.js"
></script>

The ESM build automatically loads vendor chunks on demand:

| Chunk | Size | Gzipped | Description | | --------------------- | ------ | ------- | ----------------- | | vendor-react | 822 KB | 177 KB | React/ReactDOM | | vendor-codemirror | 1.7 MB | 579 KB | CodeMirror editor | | vendor-jupyter-core | 1.2 MB | 300 KB | JupyterLab core | | vendor-mathjax | 864 KB | 203 KB | Math rendering | | vendor-xterm | 489 KB | 119 KB | Terminal emulator | | vendor-lumino | 200 KB | 49 KB | Lumino widgets |

Benefits:

  • Vendor chunks are cached independently (they rarely change)
  • Browser loads chunks in parallel
  • Only changed code needs re-downloading on updates

Build the ESM version with:

npm run build:esm

npm (Node.js / Bundler)

npm install @datalayer/jupyter-embed
# or
yarn add @datalayer/jupyter-embed
import {
  configureJupyterEmbed,
  initJupyterEmbeds,
} from '@datalayer/jupyter-embed';

configureJupyterEmbed({
  serverUrl: 'http://localhost:8888',
  token: 'your-token',
});

initJupyterEmbeds();

Configuration Options

| Option | Type | Default | Description | | ----------------- | --------------------- | ----------- | ------------------------------------------- | | serverUrl | string | '' | Jupyter server URL | | wsUrl | string | derived | WebSocket URL (auto-derived from serverUrl) | | token | string | '' | Authentication token | | defaultKernel | string | 'python3' | Default kernel name | | autoStartKernel | boolean | true | Auto-start kernel | | lazyLoad | boolean | true | Lazy load components when visible | | theme | 'light' | 'dark' | 'light' | Theme | | basePath | string | '/' | Base path for Jupyter server |

Attribute Convention

All attributes use the data-jupyter-* prefix for clarity and to avoid conflicts with other libraries.

Attribute Patterns

| Component | Source Code | Auto-Execute | Height | | ------------ | -------------------------------------------------------- | --------------------------- | --------------------- | | Cell | data-jupyter-code or <code data-jupyter-source-code> | data-jupyter-auto-execute | data-jupyter-height | | Output | data-jupyter-code or <code data-jupyter-source-code> | data-jupyter-auto-run | data-jupyter-height | | Terminal | N/A | N/A | data-jupyter-height | | Notebook | N/A | N/A | data-jupyter-height | | Console | <code data-jupyter-pre-execute-code> | N/A | data-jupyter-height |

Backward Compatibility

Short-form attributes (without data-jupyter- prefix) are also supported for backward compatibility:

| Prefixed Form (Recommended) | Short Form (Legacy) | | --------------------------------- | ----------------------------------------- | | data-jupyter-embed="cell" | data-jupyter-embed + data-type="cell" | | data-jupyter-height | data-height | | data-jupyter-auto-execute | data-auto-execute | | data-jupyter-code | data-source or data-code | | <code data-jupyter-source-code> | <code data-type="source-code"> |

Component Types

Code Cell

<div
  data-jupyter-embed="cell"
  data-jupyter-cell-type="code"
  data-jupyter-height="200px"
  data-jupyter-auto-execute="true"
  data-jupyter-show-toolbar="true"
  data-jupyter-kernel="python3"
>
  <code data-jupyter-source-code>
    # Your Python code here print("Hello!")
  </code>
</div>

Or using inline code attribute:

<div
  data-jupyter-embed="cell"
  data-jupyter-code="print('Hello!')"
  data-jupyter-height="200px"
  data-jupyter-auto-execute="true"
></div>

Attributes:

  • data-jupyter-cell-type: code | markdown | raw (default: code)
  • data-jupyter-height: CSS height value
  • data-jupyter-auto-execute: Auto-run on load (default: true)
  • data-jupyter-show-toolbar: Show cell toolbar (default: true)
  • data-jupyter-kernel: Kernel name override

Notebook

<!-- From server path -->
<div
  data-jupyter-embed="notebook"
  data-jupyter-path="path/to/notebook.ipynb"
  data-jupyter-height="500px"
  data-jupyter-readonly="false"
  data-jupyter-show-toolbar="true"
></div>

<!-- From URL -->
<div
  data-jupyter-embed="notebook"
  data-jupyter-url="https://example.com/notebook.ipynb"
></div>

<!-- Inline content -->
<div data-jupyter-embed="notebook">
  <script type="application/json">
    {
      "cells": [...],
      "metadata": {...},
      "nbformat": 4,
      "nbformat_minor": 4
    }
  </script>
</div>

Terminal

<div
  data-jupyter-embed="terminal"
  data-jupyter-height="300px"
  data-jupyter-color-mode="dark"
  data-jupyter-terminal-name="main"
></div>

Console

<div
  data-jupyter-embed="console"
  data-jupyter-height="400px"
  data-jupyter-kernel="python3"
>
  <code data-jupyter-pre-execute-code>
    # Code to run on console start import numpy as np
  </code>
</div>

Output (Display Only)

<!-- Execute code and display output -->
<div
  data-jupyter-embed="output"
  data-jupyter-height="300px"
  data-jupyter-auto-run="true"
>
  <code data-jupyter-source-code>
    import matplotlib.pyplot as plt import numpy as np x = np.linspace(0, 10,
    100) plt.plot(x, np.sin(x)) plt.title('Sine Wave') plt.show()
  </code>
</div>

<!-- Or with inline code attribute -->
<div
  data-jupyter-embed="output"
  data-jupyter-code="print('Hello, World!')"
  data-jupyter-auto-run="true"
></div>

<!-- Pre-computed output (no execution) -->
<div data-jupyter-embed="output">
  <script type="application/json">
    [
      {
        "output_type": "stream",
        "name": "stdout",
        "text": "Hello, World!\n"
      }
    ]
  </script>
</div>

JavaScript API

// Configure connection
JupyterEmbed.configureJupyterEmbed({
  serverUrl: 'http://localhost:8888',
  token: 'your-token',
  defaultKernel: 'python3',
  lazyLoad: true,
});

// Initialize all embeds in page
JupyterEmbed.initJupyterEmbeds();

// Initialize embeds in a specific container (e.g., after AJAX load)
JupyterEmbed.initAddedJupyterEmbeds(containerElement);

// Render programmatically
const element = document.getElementById('my-embed');
JupyterEmbed.renderEmbed(element, {
  type: 'cell',
  source: 'print("Hello")',
  autoExecute: true,
});

// Unmount specific embed
JupyterEmbed.unmountEmbed(element);

// Destroy all embeds
JupyterEmbed.destroyJupyterEmbeds();

React Integration

For React applications, you can use the components directly:

import {
  JupyterWrapper,
  CellEmbed,
  NotebookEmbed,
} from '@datalayer/jupyter-embed';

function App() {
  return (
    <div>
      <CellEmbed
        options={{
          type: 'cell',
          source: 'print("Hello!")',
          autoExecute: true,
        }}
      />
    </div>
  );
}

Or use the full @datalayer/jupyter-react library for more control.

Styling

Hide uninitialized embeds to prevent flash of unstyled content:

[data-jupyter-embed]:not([data-jupyter-initialized]) {
  visibility: hidden;
  min-height: 100px;
}

Requirements

  • A running Jupyter server with:
    • CORS configured to allow your domain
    • Token authentication or no authentication
    • WebSocket support enabled

Example Jupyter Server Configuration

# jupyter_server_config.py
c.ServerApp.allow_origin = '*'
c.ServerApp.allow_credentials = True
c.ServerApp.token = 'your-secure-token'
c.ServerApp.disable_check_xsrf = True

Or start with:

jupyter server --ServerApp.allow_origin='*' --ServerApp.token='your-token'

Browser Support

IIFE Build (Single File)

  • Chrome 80+
  • Firefox 75+
  • Safari 13.1+
  • Edge 80+

ESM Build (Chunked)

  • Chrome 61+ (ES modules support)
  • Firefox 60+
  • Safari 11+
  • Edge 79+

Build Outputs

| Build | Command | Output | Size | Use Case | | ------------- | ------------------- | --------------------------- | ------------------- | --------------------------- | | IIFE | npm run build | dist/jupyter-embed.js | 13 MB (3.4 MB gzip) | Simple script tag inclusion | | ESM (single) | npm run build | dist/jupyter-embed.esm.js | 13 MB (3.4 MB gzip) | ES module import | | ESM (chunked) | npm run build:esm | dist-esm/ | 11 MB total | Production with caching |

Development

Running Examples Locally

Build the lazy-loading version and serve examples on http://localhost:3456:

make example

This will:

  • Build the lazy-loading chunked version (build:lazy)
  • Copy artifacts to the examples/ directory
  • Serve examples at:
    • http://localhost:3456/ - Standard examples (index.html)
    • http://localhost:3456/index-lazy.html - Lazy loading demo

The examples use the hosted Jupyter server at https://prod1.datalayer.run/api/jupyter-server.

Deploying to CDN

Deploy to the production CDN (https://jupyter-embed.datalayer.tech):

make deploy

This will:

  • Build the lazy-loading version
  • Prepare deployment artifacts in build/:
    • jupyter-embed.lazy.js - Main entry point (~100KB)
    • chunks/ - Component chunks (loaded on-demand)
    • index.html - Standard examples
    • index-lazy.html - Lazy loading demo
  • Upload to S3 bucket s3://datalayer-jupyter-embed/
  • Invalidate CloudFront cache for immediate availability

Note: Deployment requires AWS credentials with the datalayer profile configured.

License

MIT © Datalayer

Related Projects