Back to Streamlit

Streamlit Dashboard App Templates

lib/streamlit/.agents/skills/developing-with-streamlit/assets/templates/apps/README.md

1.57.1.dev202605184.8 KB
Original Source

Streamlit Dashboard App Templates

This directory contains ready-to-use dashboard templates for Streamlit. Each template demonstrates best practices for building data-driven dashboards with modern UI patterns.

Available Templates

Public Demo Templates

These templates are based on official Streamlit demo apps and work out of the box:

TemplateDescriptionKey Features
dashboard-seattle-weatherWeather data exploration dashboardst.metric, st.pills, st.altair_chart, year comparison
dashboard-stock-peersStock peer analysis and comparisonst.multiselect, normalized charts, peer average calculation

Analytics Dashboard Templates

These templates demonstrate common dashboard patterns with synthetic data. Replace the data generation functions with your actual data sources:

TemplateDescriptionKey Features
dashboard-metricsCore metrics dashboard with KPIsChart/table toggle, st.popover filters, TIME_RANGES (1M/6M/1Y/QTD/YTD/All)
dashboard-feature-usageAPI endpoint usage analyticsSegmented control, starter kits, normalization toggle, rolling averages
dashboard-companiesCompany leaderboard with drill-downInteractive dataframe, sparkline columns, growth scores
dashboard-computeResource consumption monitoring@st.fragment, st.popover filters, TIME_RANGES, line/bar toggle

Quick Start

Run a Template Locally

bash
# Navigate to a template directory
cd assets/templates/apps/dashboard-metrics

# Sync dependencies from pyproject.toml
uv sync

# Run the app
uv run streamlit run streamlit_app.py

Template Structure

Each template follows this structure:

dashboard-{name}/
├── streamlit_app.py    # Main application code
└── pyproject.toml      # Dependencies and metadata

Canonical Patterns

When creating new templates or adapting existing ones, follow these patterns for consistency.

Page Configuration

Always set page config as the first Streamlit call, with layout="wide" and a Material icon:

python
st.set_page_config(
    page_title="My Dashboard",
    page_icon=":material/monitoring:",
    layout="wide",
)

Constants

Use these standard constant names:

python
TIME_RANGES = ["1M", "6M", "1Y", "QTD", "YTD", "All"]
CHART_HEIGHT = 300  # Standard chart height in pixels

Time Range Filtering

All dashboard templates that support time filtering use the same filter_by_time_range function:

python
def filter_by_time_range(df: pd.DataFrame, x_col: str, time_range: str) -> pd.DataFrame:
    """Filter dataframe by time range."""
    if time_range == "All" or df.empty:
        return df

    df = df.copy()
    df[x_col] = pd.to_datetime(df[x_col])
    max_date = df[x_col].max()

    if time_range == "1M":
        min_date = max_date - timedelta(days=30)
    elif time_range == "6M":
        min_date = max_date - timedelta(days=180)
    elif time_range == "1Y":
        min_date = max_date - timedelta(days=365)
    elif time_range == "QTD":
        quarter_month = ((max_date.month - 1) // 3) * 3 + 1
        min_date = pd.Timestamp(date(max_date.year, quarter_month, 1))
    elif time_range == "YTD":
        min_date = pd.Timestamp(date(max_date.year, 1, 1))
    else:
        return df

    filtered: pd.DataFrame = df[df[x_col] >= min_date]
    return filtered

Popover Filters

Compact filter controls using st.popover:

python
with st.popover("Filters", type="tertiary"):
    line_options = st.pills("Lines", ["Daily", "7-day MA"], selection_mode="multi")
    time_range = st.segmented_control("Time range", TIME_RANGES, default="All")

Page Header with Reset Button

python
def render_page_header(title: str):
    """Render page header with title and reset button."""
    with st.container(
        horizontal=True, horizontal_alignment="distribute", vertical_alignment="center"
    ):
        st.markdown(title)
        if st.button(":material/restart_alt: Reset", type="tertiary"):
            st.session_state.clear()
            st.rerun()

Independent Widget Updates with @st.fragment

python
@st.fragment
def metric_card():
    with st.container(border=True):
        # This widget updates independently without full page rerun
        ...

Data Loading with Caching

python
@st.cache_data(ttl=3600)
def load_metric_data() -> pd.DataFrame:
    """Load metric data. Replace with your actual data source."""
    # Replace this with:
    # - API call
    # - Database query
    # - Data warehouse query via st.connection
    return generate_synthetic_data()

Dependencies

All templates require Python >=3.10 and use:

  • streamlit
  • altair>=5.5.0
  • pandas>=2.2.3
  • numpy>=1.26.0 (most templates)