Skip to main content

A native Reflex component wrapping jupyter-renderer-react to render Jupyter notebooks (.ipynb) in pure Python.

Project description

reflex-jupyter-renderer-react

PyPI version Python versions License: MIT GitHub

A native Reflex component that wraps the jupyter-renderer-react React library, so you can render Jupyter notebooks (.ipynb) in a Reflex app — with syntax highlighting, markdown, rich outputs, theming, collapsible cells and copy-to-clipboard — in pure Python. No HTML, no iframe, no hand-written JavaScript.

import reflex as rx
from reflex_jupyter_renderer_react import (
    jupyter_notebook_viewer, Notebook, MarkdownCell, CodeCell, stream_output,
)

nb = Notebook(cells=[
    MarkdownCell("# Hello, notebook"),
    CodeCell("print('hi')", execution_count=1, outputs=[stream_output("hi\n")]),
])

def index() -> rx.Component:
    return jupyter_notebook_viewer(notebook=nb.to_dict(), theme="dark")

app = rx.App()
app.add_page(index)

Why a native component?

iframe / pre-rendered HTML native component (this package)
Isolated from app state Wired into Reflex state via events (on_file_load, on_error, …)
Tied to static files/routes Reusable, pip install-able
Untyped JSON edited by hand Typed Python builders for notebooks
External hosting / manual embedding npm dependency resolved by Reflex automatically

Install

pip install reflex-jupyter-renderer-react
# or, with uv:
uv add reflex-jupyter-renderer-react
# or, from this repo (editable):
uv pip install -e .

Reflex installs the underlying npm package (jupyter-renderer-react) into the compiled frontend automatically on the first reflex run.

Usage

Three ways to supply a notebook

from reflex_jupyter_renderer_react import (
    jupyter_notebook_viewer, JupyterNotebookViewer, Notebook, MarkdownCell, CodeCell,
    load_notebook,
)

# 1) Typed Python builders
nb = Notebook(cells=[MarkdownCell("# Title"), CodeCell("1 + 1", execution_count=1)])
jupyter_notebook_viewer(notebook=nb.to_dict())

# 2) A raw JSON string
jupyter_notebook_viewer(notebook='{"cells": [], "nbformat": 4, "nbformat_minor": 4}')
# or: JupyterNotebookViewer.from_json(json_str)

# 3) Load from a URL or from disk
JupyterNotebookViewer.from_url("https://example.com/notebook.ipynb")
jupyter_notebook_viewer(notebook=load_notebook("assets/demo-example.ipynb"))

Props

Prop Type Default Description
notebook dict | str required Parsed dict, JSON string, or {"filePath": "..."}.
theme str | dict "light" "light", "dark", or a custom theme object.
show_cell_numbers bool True Show execution count for code cells.
show_outputs bool True Render cell outputs.
collapsible bool False Allow cells to collapse.
copyable bool True Copy button on code cells.
class_names dict {} Per-part class names (classNames).
styles dict {} Per-part inline styles (styles).
fetch_options dict {} {"headers": {...}, "timeout": 10000} for URL loading.

Reflex converts snake_case props to camelCase automatically (show_cell_numbersshowCellNumbers).

Events → Python

class State(rx.State):
    status: str = "idle"

    @rx.event
    def loaded(self, notebook: dict):
        self.status = f"{len(notebook.get('cells', []))} cells loaded"

    @rx.event
    def failed(self, message: str):
        self.status = f"error: {message}"

JupyterNotebookViewer.from_url(
    "https://example.com/notebook.ipynb",
    fetch_options={"timeout": 10000},
    on_file_load=State.loaded,
    on_file_error=State.failed,
)
Event Payload Fires when
on_file_load notebook: dict A notebook is fetched from a filePath.
on_file_error message: str File loading fails (network / 404 / timeout).
on_error message: str Parsing / rendering fails.

Demo app

A full demo lives in jupyter_renderer_react_demo/ and exercises every feature (typed builders, JSON string, URL loading with events, custom styles, and live theme/prop toggles).

uv pip install -e .
cd jupyter_renderer_react_demo
uv run reflex run

Building notebooks in Python

from reflex_jupyter_renderer_react import (
    Notebook, MarkdownCell, CodeCell,
    stream_output, execute_result_output, error_output,
)

nb = Notebook(cells=[
    MarkdownCell("# Report"),
    CodeCell("print('hi')", execution_count=1, outputs=[stream_output("hi\n")]),
    CodeCell("2 ** 10", execution_count=2,
             outputs=[execute_result_output({"text/plain": "1024"}, execution_count=2)]),
    CodeCell("1/0", execution_count=3,
             outputs=[error_output("ZeroDivisionError", "division by zero")]),
])
data = nb.to_dict()

The data-model layer (Notebook, cells, output factories, load_notebook) imports without Reflex installed, so it is usable in plain scripts and unit tests.

Naming note

The upstream project has some naming inconsistencies. This wrapper centralizes them in overridable constants and defaults to the public, documented contract:

Source Name
Public README usage JupyterNotebookViewer
src/index.ts export JupiterNotebookViewer (sic)
package.json name @iomete/jupyter-renderer-react (GitHub registry)

Defaults: library = "jupyter-renderer-react", tag = "JupyterNotebookViewer". To retarget the scoped package or the source-spelled tag:

import reflex_jupyter_renderer_react.jupyter_renderer_react as j
j.JupyterNotebookViewer.library = "@iomete/jupyter-renderer-react"
j.JupyterNotebookViewer.tag = "JupiterNotebookViewer"

You can also pin a version via LIBRARY_VERSION in custom_components/reflex_jupyter_renderer_react/jupyter_renderer_react.py.

Development

This project follows the Reflex custom component workflow and uses uv.

uv venv
uv pip install -e ".[dev]"
uv run pytest                 # run the tests

# Publish (custom component flow)
reflex component build        # -> dist/
uv publish                    # or: twine upload dist/*
reflex component share        # list in the Reflex gallery

See specs/ for the full Spec-Driven Design documentation: PRD, architecture, API, data-model schema, and the phased implementation plan & tasks.

Project structure

reflex-jupyter-renderer-react/
├── custom_components/reflex_jupyter_renderer_react/
│   ├── __init__.py
│   ├── jupyter_renderer_react.py   # the Reflex component
│   └── models.py                   # dependency-free notebook builders
├── jupyter_renderer_react_demo/    # runnable demo app
├── tests/                          # data-model + component contract tests
├── specs/                          # SDD: prd / technical / api / data-model / plans
├── pyproject.toml
├── README.md · CHANGELOG.md · LICENSE

License

MIT © Ernesto Crespo. The upstream jupyter-renderer-react library is also MIT.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

reflex_jupyter_renderer_react-0.1.0.tar.gz (15.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

reflex_jupyter_renderer_react-0.1.0-py3-none-any.whl (13.6 kB view details)

Uploaded Python 3

File details

Details for the file reflex_jupyter_renderer_react-0.1.0.tar.gz.

File metadata

File hashes

Hashes for reflex_jupyter_renderer_react-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3abbac8e1d3bc26bdfbbfdbface1b23a3509944734884234ae19970b0df2666e
MD5 c495ca5de171e92d517a54672b8aecc6
BLAKE2b-256 58b97d1a3bfc5638b82ca6bc51326e8e9a8232aea6a5c3ccc9cda4a7eb4de765

See more details on using hashes here.

File details

Details for the file reflex_jupyter_renderer_react-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for reflex_jupyter_renderer_react-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 90e848fcf9bb9c0e961a413df808abbccc56cc6d521d0245385dc71d79822498
MD5 0868ab81457287d528f47bbcd22b53f4
BLAKE2b-256 96241cab19be40f438aad1662850735b644a4fa20ab37dbed6f005db021fb042

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page