Embedding
September 23, 2026 ยท View on GitHub
show() is a convenience for local exploration: it registers the data
source, starts a server thread, and opens a browser. For anything longer
lived, run the server yourself.
Standalone server
Register named sources, then run the FastAPI app like any other:
import polars as pl
import uvicorn
from flexviz import app, register_source
register_source("trips", pl.scan_parquet("trips.parquet"))
register_source("weather", pl.scan_parquet("weather.parquet"), cache=True)
uvicorn.run(app, host="127.0.0.1", port=8000)
Register all sources before the server starts; the registry is the only
server-side state and is read-only during request handling. Pass
cache=True for static sources to enable
caching and live brushing.
Because the server is stateless, it scales horizontally without session affinity: any replica can answer any request.
Mounting into an existing FastAPI app
mount_into adds the FlexViz routes to an app you already have:
from fastapi import FastAPI
from flexviz import mount_into, register_source
app = FastAPI()
register_source("trips", lf)
mount_into(app, prefix="/flexviz")
The FlexViz endpoints (/dashboard/update, /share, /view,
/sources) then live under the prefix. The mounted app brings its own gzip
middleware, so responses are compressed regardless of the host app's setup.
For Flask or other WSGI hosts, use
werkzeug.middleware.dispatcher.DispatcherMiddleware instead.
Serving a dashboard from a URL
A browser opens a view through GET /view?spec=<encoded>. To hand out a
dashboard URL from your own code, build the spec and ask the server to encode
it, or use the toolbar's share button from a rendered view (see
Sharing views). The /view page talks to the API with
page-relative URLs, so it works unchanged behind a reverse proxy or path
prefix.
In an iframe
A /view URL is a complete page, so any web app can embed it in an iframe.
Build the URL with share_url() against a server that already serves the
source. The server_url must be reachable from the browser; 127.0.0.1 only
works when the browser and Python server run on the same machine.
import polars as pl
import uvicorn
from flexviz import Dashboard, LayoutSpec, ToolbarConfig, app, register_source
lf = pl.scan_parquet("readings.parquet")
register_source("readings", lf, cache=True)
dash = Dashboard(lf, cache=True)
dash.add_figure(title="Power").add_line(x="timestamp", y="power")
url = dash.share_url(
server_url="http://127.0.0.1:8000",
source_name="readings",
cols=1, # one full-width panel instead of the half-width default
draggable=False, # read-only: no drag, no resize, no layout button
layout=LayoutSpec(toolbar=ToolbarConfig(show_export=False, show_import=False)),
)
print(url)
uvicorn.run(app, host="127.0.0.1", port=8000)
Then embed the URL. In React:
<iframe src={url} style={{ width: "100%", height: "600px", border: 0 }} />
Who owns width and height
The parent page owns the iframe box. FlexViz owns what is inside it.
- Width is responsive. Panels are a 12-column grid at
width: 100%, and the charts resize with their container.cols=1gives one full-width panel. - Height is fixed. A panel spans
GridItem.hgrid rows of 80 px, so it ish * 80pixels tall.gapdoes not change this, and neither doesdraggable. The page is as tall as its panels plus the toolbar. It does not stretch to fill the iframe.
To approach a given iframe height, set GridItem.h yourself:
from flexviz import GridItem, LayoutSpec
uid = dash.to_spec().figures[0].uid
url = dash.share_url(
server_url="http://127.0.0.1:8000",
source_name="readings",
draggable=False,
layout=LayoutSpec(grid_items=[GridItem(fig_uid=uid, x=0, y=0, w=12, h=7)]),
)
h=7 is 560 px of panel. Leave room for the toolbar above it, or let the
iframe scroll. There is no mode that makes the dashboard fill its parent.
!!! warning "height= is notebook-only"
show(height=...) sets the height of the inline notebook iframe. It does
not size a browser page, and /view never reads it. For an iframe you own,
set the height on the iframe element.
See Customizing for the full LayoutSpec, GridItem and
ToolbarConfig reference.