Skip to content

Getting Started with the PanelLive Component

This tutorial shows you how to use the PanelLive component in a Panel server application. PanelLive wraps the <panel-live> web component as a Panel JSComponent, letting you run Python code client-side via Pyodide with bidirectional data exchange.

Embedding in HTML panes, Markdown panes, or ChatInterface?

If you want to embed <panel-live> directly inside pn.pane.HTML, pn.pane.Markdown, or pn.chat.ChatInterface without the JSComponent, see HTML & Markdown Panes.

Installation

uv pip install git+https://github.com/panel-extensions/panel-live.git

Pre-release

panel-live has not been published to npm or PyPI yet. The install command above uses a GitHub source install, which works now. Once released, it will change to:

  • Python: uv pip install panel-live

Quick Start

Create a file app.py:

import panel as pn
from panel_live import PanelLive

pn.extension()

editor = PanelLive(
    code='import panel as pn\npn.panel("Hello from Pyodide!").servable()',
    mode="editor",
    auto_run=True,
)

pn.Column("## My First PanelLive App", editor).servable()

Serve it:

panel serve app.py

Open http://localhost:5006/app in your browser. You'll see a code editor with live Pyodide output.

Display Modes

PanelLive supports six display modes:

# Code editor + output (default)
PanelLive(code="...", mode="editor")

# Output only — no editor visible
PanelLive(code="...", mode="app")

# Editor + examples selector
PanelLive(code="...", mode="playground")

# Spinning Python icon — evaluate() queue on hover
PanelLive(code="...", mode="progress")

# stdout/stderr visible — for development
PanelLive(code="...", mode="debug")

# Invisible (0px) — pure background compute
PanelLive(code="...", mode="headless")

Sending Data to the Client

Set the input param to push data from the server to client-side code. On the client side, the data is available as server.input (a reactive Param parameter):

import panel as pn
from panel_live import PanelLive

pn.extension()

live = PanelLive(
    code="""\
import panel as pn

@pn.depends(server.param.input)
def show(value):
    return value or "Waiting for server data..."

pn.pane.JSON(show, depth=2).servable()
""",
    mode="editor",
    auto_run=True,
)

button = pn.widgets.Button(name="Send Data", button_type="primary")

def on_click(event):
    live.input = {"message": "Hello from the server!", "timestamp": 42}

button.on_click(on_click)

pn.Column(button, live).servable()

Receiving Data from the Client

On the client side, set server.output to send data back. On the server side, watch the output param:

import panel as pn
from panel_live import PanelLive

pn.extension()

live = PanelLive(
    code="""\
import panel as pn

btn = pn.widgets.Button(name="Send to Server", button_type="primary")
count = 0

def on_click(event):
    global count
    count += 1
    server.output = {"count": count, "source": "browser"}

btn.on_click(on_click)
pn.Column(btn, "Click to send data to the server").servable()
""",
    mode="editor",
    auto_run=True,
)

result = pn.pane.JSON(name="Client Output")

def on_output(event):
    result.object = live.output

live.param.watch(on_output, "output")

pn.Column(live, result).servable()

Remote Code Execution

Use evaluate() to execute arbitrary Python code in the browser and get results back:

import panel as pn
from panel_live import PanelLive

pn.extension()

live = PanelLive(mode="progress", auto_run=True, code="pass")

async def compute():
    result = await live.evaluate(
        "result = sum(range(n))",
        n=100,
    )
    return result

pn.Column(
    live,
    pn.pane.Str(pn.bind(compute)),
).servable()

Showcase App

Run the built-in showcase that demonstrates all modes:

uvx --from git+https://github.com/panel-extensions/panel-live panel-live serve --port 5008

PanelLive Showcase

Future: shorter command

Once panel-live is published to PyPI, this simplifies to uvx panel-live serve.

Local Assets

For local development without CDN, serve the panel-live JS/CSS as static files:

from panel_live import PanelLive

# Point to locally served assets
PanelLive.configure(
    js_url="./pl/panel-live.js",
    css_url="./pl/panel-live.css",
)

Then serve with --static-dirs:

panel serve app.py --static-dirs pl=dist

CDN assets

By default, PanelLive loads JS/CSS from GitHub Pages (panel-extensions.github.io/panel-live/assets/). Once published to npm, the default CDN will change to cdn.jsdelivr.net/npm/@panel-extensions/panel-live@latest/dist/. Use PanelLive.configure() to override with local assets for offline development.

Next Steps