Skip to content

Streamlit Integration

Render a dbt Charts board inside a Streamlit app with st_board(), from the dbt-charts[streamlit] extra.

Installation

pip install "dbt-charts[streamlit]"

Requires Streamlit 1.51 or later.

Usage

import streamlit as st
from dbt_charts.integrations.streamlit import st_board

st.title("Revenue")
st_board("charts/revenue.yml", project_dir="path/to/your/project")

st_board() compiles and renders the board (inline SVG, no external requests) and mounts it at the width of its Streamlit column, keeping the board's proportions. A board that fails as a whole raises, rather than drawing an empty frame. A single chart that fails still draws, as an error card in its place.

Variable controls

The board's own variable controls work the way they do under dct serve: a viewer opens a control, picks a value, and the board renders again with it. Tabs work the same way. The app needs no widgets of its own for this.

What the viewer picked is kept in Streamlit's session state, one entry per board path. Pass key= to mount the same board twice on one page.

Setting a variable from the app

variables= sets a board's variables: from the app, for example from a Streamlit widget. A value the app passes wins over what the viewer picks in the board, so pass only the variables the app owns. The board still draws a control for such a variable, and a pick there is overridden on the next render:

import streamlit as st
from dbt_charts.integrations.streamlit import st_board

year = st.selectbox("Year", [2023, 2024, 2025])
st_board(
    "charts/revenue.yml",
    project_dir="path/to/your/project",
    variables={"year": year},
)

Streamlit in Snowflake

Streamlit in Snowflake (SiS) apps run with a live Snowpark session and no dbt profile to connect with. Pass that session in, and SQL queries against a snowflake source run through it instead:

import streamlit as st
from snowflake.snowpark.context import get_active_session
from dbt_charts.integrations.streamlit import st_board

session = get_active_session()
st_board(
    "charts/revenue.yml",
    project_dir="path/to/your/project",
    session=session,
)

Without session=, st_board() renders like any other local dbt Charts project (DuckDB or a local dbt profile).

These limits apply to queries that run through the session:

  • A query with setup_sql: is refused, because a Snowpark session runs one statement per call.
  • The session must be using the database and schema the source declares. Unqualified table names resolve in the session's current database and schema, so a mismatch is refused with an error naming both. Call session.use_database(...) and session.use_schema(...) before st_board().
  • The source's account, role, and warehouse are not applied. Queries run in the session's account, with its role's privileges, on its warehouse.
  • A refused or failed query shows as an error card on its chart.
  • A source's attribution: labels are not sent. They travel in the dbt query header, which this path does not use.
  • A source's max_query_duration_seconds is not applied. The session belongs to the app, so statement timeouts are whatever the app set on it.

Reruns re-query

Streamlit re-runs the whole script on every interaction, including a pick in a board control, and each st_board() call compiles the board and runs its queries again. Against a warehouse that is billed work on every click. Snowflake's own result cache serves a repeated identical query at no compute cost; beyond that, caching is the app's job.

Container runtime notes

SiS apps that need dbt-charts[streamlit] from PyPI run in container runtime, not the default warehouse runtime, which has no outbound package access. Container runtime reaches PyPI through either an artifact repository you configure, or an external access integration your account admin grants.

Whose privileges the queries run with

By default a Streamlit in Snowflake app runs with owner's rights: queries run as the app owner's role, so a row access policy evaluates against the owner and every viewer sees the same rows. Snowflake documents a restricted caller's rights option for container-runtime apps. Read their page before relying on per-viewer row policies inside an app.

Not yet verified

These have not been verified against a real Streamlit in Snowflake (SiS) environment:

  • Queries through a live Snowpark session.
  • Whether SiS's content-security policy allows the inline <script> a rendered board carries. That script drives hover states and the variable controls. If it is blocked, the charts and layout still render, without tooltips and with controls that do not respond.
  • Whether the full dbt-charts[streamlit] dependency set installs cleanly in SiS's container runtime.