Skip to content

The app.show() Method

app.show() is the primary entry point for rendering content in PyWry. It accepts HTML (as a string or HtmlContent object), determines the correct rendering path for the current environment, and returns a handle you can use to interact with the result.

Basic Usage

from pywry import PyWry

app = PyWry()

# Simplest form — just a string of HTML
app.show("<h1>Hello, world!</h1>")

This single call does everything: it detects whether you're in a terminal, a Jupyter notebook, or browser mode — then opens a native window, renders an anywidget, or starts a server accordingly.

Signature

app.show(
    content,                    # str | HtmlContent — the HTML to render
    title=None,                 # str — window title (native mode)
    width=None,                 # int | str — width in pixels (int) or CSS value (str, e.g. "60%")
    height=None,                # int — height in pixels
    callbacks=None,             # dict[str, Callable] — event handlers
    include_plotly=False,       # bool — load the Plotly.js library
    include_aggrid=False,       # bool — load the AG Grid library
    aggrid_theme="alpine",      # str — AG Grid theme name
    label=None,                 # str — window label for multi-window targeting
    watch=None,                 # bool — enable hot reload for CSS/JS files
    toolbars=None,              # list[Toolbar | dict] — toolbar configurations
    modals=None,                # list[Modal | dict] — modal dialog configurations
)

Parameters in Detail

content — what to render

Accepts either a plain HTML string or an HtmlContent object. When you pass a string, PyWry wraps it in a minimal document structure automatically. When you pass HtmlContent, you get control over CSS files, JS files, inline styles, JSON data injection, and hot reload watching. See the HtmlContent guide for details.

# Plain string — PyWry wraps it in a full HTML document
app.show("<div id='app'>Hello</div>")

# HtmlContent — full control over assets
from pywry import HtmlContent

content = HtmlContent(
    html="<div id='app'>Hello</div>",
    css_files=["styles/app.css"],
    script_files=["scripts/app.js"],
    inline_css="body { background: #1a1a2e; color: white; }",
    json_data={"items": [1, 2, 3]},
    watch=True,
)
app.show(content)

title — window title

Sets the title bar text in native window mode. Defaults to "PyWry". Ignored in notebook and browser modes.

app.show("<h1>Dashboard</h1>", title="Sales Dashboard")

width and height — dimensions

In native mode, width accepts an integer (pixels) for the OS window size. In notebook mode, width can also be a CSS string like "100%" or "500px". height is always an integer (pixels).

# Native window: 800×600 pixels
app.show(html, width=800, height=600)

# Notebook: full-width, 400px tall
app.show(html, width="100%", height=400)

Defaults come from WindowConfig — 1280×720 unless overridden in your configuration.

callbacks — event handlers

A dictionary mapping event names to Python callback functions. These are registered before the content is rendered, so they're ready to receive events immediately.

def on_click(data, event_type, label):
    print(f"Clicked: {data}")

def on_save(data, event_type, label):
    print("Saving...")

app.show(html, callbacks={
    "plotly:click": on_click,
    "app:save": on_save,
})

See the Event System guide for the full callback signature and registration patterns.

include_plotly and include_aggrid — library loading

When True, PyWry injects the Plotly.js or AG Grid JavaScript and CSS libraries into the page. You don't need to set these manually if you use app.show_plotly() or app.show_dataframe() — they set the flags automatically.

# Manual: include Plotly when using raw HTML with Plotly
app.show(plotly_html, include_plotly=True)

# Automatic: show_plotly() handles this for you
app.show_plotly(fig)

label — window identity

In MULTI_WINDOW mode, the label identifies which window to create or update. In SINGLE_WINDOW mode, the label is fixed and this parameter is ignored. Labels are used in callbacks to target events back to a specific window.

from pywry import PyWry, WindowMode

app = PyWry(mode=WindowMode.MULTI_WINDOW)
app.show(chart_html, label="chart")
app.show(table_html, label="table")

# Later, inside a callback:
def on_filter(data, event_type, label):
    app.emit("app:update", {"filter": data}, "chart")  # target the chart window

watch — hot reload

When True, PyWry watches the CSS and JS files referenced by HtmlContent.css_files and HtmlContent.script_files for changes, and live-reloads them in the browser without a full page refresh.

content = HtmlContent(
    html="<div>Dashboard</div>",
    css_files=["styles/dashboard.css"],
    watch=True,  # or set it here
)
app.show(content, watch=True)  # or override here

See the Hot Reload guide for details.

toolbars and modals — UI chrome

Lists of Toolbar or Modal objects (or their dict equivalents) that wrap your content in an interactive layout. Toolbars are positioned around the content area; modals are hidden until triggered by events.

from pywry import Toolbar, Button, TextInput, Modal

toolbar = Toolbar(position="top", items=[
    Button(label="Save", event="app:save"),
    TextInput(label="Search", event="app:search"),
])

modal = Modal(id="settings", title="Settings", items=[
    TextInput(label="Name", event="settings:name"),
    Button(label="Apply", event="settings:apply"),
])

app.show(html, toolbars=[toolbar], modals=[modal])

See the Toolbar System guide for the full component list and layout positions.

Return Value

app.show() returns a handle that provides a consistent API regardless of rendering path:

handle = app.show(html)

# Send events to this specific window/widget
handle.emit("pywry:set-content", {"selector": "h1", "text": "Updated"})

# Register additional callbacks
handle.on("app:click", on_click)

The returned type depends on the environment:

Environment Return Type Transport
Desktop terminal NativeWindowHandle stdin pipe → Tauri IPC
Jupyter (with anywidget) PyWryWidget traitlet sync
Jupyter (IFrame fallback) InlineWidget WebSocket
Browser mode InlineWidget WebSocket

All implement the BaseWidget protocol, so emit() and on() work identically.

Convenience Methods

app.show() is the general-purpose method. PyWry also provides specialized variants that configure the right options automatically:

app.show_plotly(figure, ...)

Converts a Plotly figure to HTML, injects Plotly.js, and pre-wires chart events (plotly:click, plotly:hover, plotly:selected, plotly:relayout).

import plotly.express as px

fig = px.scatter(x=[1, 2, 3], y=[1, 4, 9])
app.show_plotly(fig, callbacks={"plotly:click": on_click})

app.show_dataframe(data, ...)

Converts a DataFrame to AG Grid HTML, injects the AG Grid library, and pre-wires grid events (grid:cell-clicked, grid:selection-changed, grid:cell-edited).

import pandas as pd

df = pd.DataFrame({"Name": ["Alice", "Bob"], "Score": [95, 87]})
app.show_dataframe(df, callbacks={"grid:cell-clicked": on_cell})

Both methods accept all the same optional parameters as app.show() (title, width, height, callbacks, label, toolbars, modals).

Rendering Path Selection

app.show() detects the environment and selects the rendering path automatically:

flowchart TD
    A["app.show(content)"] --> B{"mode = BROWSER?"}
    B -- Yes --> C["InlineWidget<br>FastAPI + WebSocket<br>opens system browser"]
    B -- No --> D{"In a notebook?"}
    D -- Yes --> E{"include_plotly<br>or include_aggrid?"}
    E -- Yes --> F["InlineWidget<br>IFrame + WebSocket<br>specialized JS"]
    E -- No --> G{"anywidget<br>available?"}
    G -- Yes --> H["PyWryWidget<br>anywidget + traitlet sync"]
    G -- No --> I["InlineWidget<br>IFrame + WebSocket<br>fallback"]
    D -- No --> J["NativeWindowHandle<br>PyTauri + OS webview"]

You can force a specific mode by setting it on the app:

from pywry import PyWry, WindowMode

# Always use native windows (even in notebooks)
app = PyWry(mode=WindowMode.SINGLE_WINDOW)

# Always use browser
app = PyWry(mode=WindowMode.BROWSER)

Next Steps