For the complete documentation index, see llms.txt. This page is also available as Markdown.

Rendering Plotly charts with the IFrame widget

Guide explains how to render Plotly charts in an app GUI using the IFrame widget

Supervisely's widget library has no native Plotly component, so the common pattern is: build a Plotly figure, export it to a static .html file, and display that file through the IFrame widget.

How it works, in short

  1. Plotly renders a figure to a self-contained HTML file.

  2. That file is saved into your app's static_dir.

  3. The IFrame widget points at that file (by its path relative to static_dir) and displays it in the GUI.

  4. To update the chart, you write a new HTML file and call iframe.set(...) again.

1. Imports

import os
from pathlib import Path
import numpy as np
import plotly.graph_objects as go
import supervisely as sly
from supervisely.app.widgets import Container, Button, IFrame

2. Create a folder for generated HTML files

Plotly needs somewhere to write its output, and that location must live inside the app's static_dir so Supervisely can serve it.

3. Declare the IFrame widget

Create it once, set a default size, and hide it until there's something to show:

You can also pass size directly in the constructor: IFrame(height="500px", width="700px").

4. Register static_dir on the Application

This is the step that's easy to miss: the folder you write Plotly HTML into must be passed as static_dir when creating the app, otherwise IFrame has nothing to serve.

5. Build the Plotly figure

Any plotly.graph_objects.Figure works. Example adapted from the source file — a 3D scatter plot separating ground vs. non-ground points:

6. Export the figure to HTML and point the IFrame at it

write_html uses your local filesystem path (previews/preview_0.html), while IFrame.set(path_to_html=...) uses the path as served under /static (static/preview_0.html). path_to_html must not start with a leading /.

Using an incrementing counter (or any unique name) for each file avoids browser caching showing a stale chart.

7. Wire it up to a button, with loading state

Putting it all together in a click handler, matching the pattern used in the source app:

(global previews_counter is needed if the counter is declared at module level, as in the original app.)

Full minimal example

Plotly chart preview

Tips and common pitfalls

The path_to_html given to IFrame.set() is relative to static_dir and must not start with a forward slash — pass static/preview_0.html, not /static/preview_0.html.

static_dir in sly.Application(...) must be the same folder Plotly's fig.write_html() writes into, just referenced by its local path (e.g. Path("previews") vs. previews/preview_0.html).

Give each generated file a unique name (counter, timestamp, or UUID) so IFrame.set() reliably shows the newest chart instead of a cached one.

Call clean_up() before generating a new chart if you want to visibly clear the widget while the next one is being computed, and toggle loading = True/False around the computation to show a spinner.

If the app deletes its working files on shutdown (as the source app does via clean_data()), make sure the previews folder isn't removed while a chart is still being viewed.

Last updated