dash

Dash Production Dashboard Skill

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "dash" with this command: npx skills add vamseeachanta/workspace-hub/vamseeachanta-workspace-hub-dash

Dash Production Dashboard Skill

Build enterprise-grade interactive dashboards with Plotly Dash. Features reactive callbacks, professional layouts, and scalable deployment for production workloads.

When to Use This Skill

USE Dash when:

  • Production dashboards - Building dashboards for business users

  • Complex interactivity - Need fine-grained control over updates

  • Enterprise requirements - Authentication, scaling, reliability needed

  • Plotly ecosystem - Already using Plotly for visualizations

  • Custom components - Need to extend with JavaScript/React

  • Long-term projects - Dashboard will be maintained and extended

  • Multi-user access - Multiple concurrent users accessing dashboards

DON'T USE Dash when:

  • Quick prototypes - Use Streamlit for faster iteration

  • Simple visualizations - Static reports may suffice

  • No interactivity needed - Use static HTML/PDF reports

  • Limited Python knowledge - Steeper learning curve than Streamlit

  • Single-user tools - Jupyter notebooks may be simpler

Prerequisites

Basic installation

pip install dash

With common extras

pip install dash plotly pandas dash-bootstrap-components

Full installation

pip install dash plotly pandas polars dash-bootstrap-components dash-ag-grid gunicorn

Using uv (recommended)

uv pip install dash plotly pandas dash-bootstrap-components dash-ag-grid

Core Capabilities

  1. Basic Application Structure

Minimal Dash App:

from dash import Dash, html, dcc import plotly.express as px import pandas as pd

Initialize app

app = Dash(name)

Sample data

df = pd.DataFrame({ "Fruit": ["Apples", "Oranges", "Bananas", "Apples", "Oranges", "Bananas"], "Amount": [4, 1, 2, 2, 4, 5], "City": ["SF", "SF", "SF", "NYC", "NYC", "NYC"] })

Create figure

fig = px.bar(df, x="Fruit", y="Amount", color="City", barmode="group")

Layout

app.layout = html.Div([ html.H1("Hello Dash"), html.P("This is a simple Dash application."), dcc.Graph(id="example-graph", figure=fig) ])

Run server

if name == "main": app.run(debug=True)

Run the app:

python app.py

Visit http://127.0.0.1:8050/

  1. Callbacks and Interactivity

Basic Callback:

from dash import Dash, html, dcc, callback, Output, Input import plotly.express as px import pandas as pd

app = Dash(name)

Sample data

df = pd.DataFrame({ "date": pd.date_range("2025-01-01", periods=100), "category": ["A", "B", "C", "D"] * 25, "value": range(100) })

Layout

app.layout = html.Div([ html.H1("Interactive Dashboard"),

html.Label("Select Category:"),
dcc.Dropdown(
    id="category-dropdown",
    options=[{"label": c, "value": c} for c in df["category"].unique()],
    value="A",
    clearable=False
),

dcc.Graph(id="line-chart")

])

Callback

@callback( Output("line-chart", "figure"), Input("category-dropdown", "value") ) def update_chart(selected_category): filtered_df = df[df["category"] == selected_category]

fig = px.line(
    filtered_df,
    x="date",
    y="value",
    title=f"Values for Category {selected_category}"
)

return fig

if name == "main": app.run(debug=True)

Multiple Inputs and Outputs:

from dash import Dash, html, dcc, callback, Output, Input import plotly.express as px import pandas as pd

app = Dash(name)

Sample data

df = pd.DataFrame({ "date": pd.date_range("2025-01-01", periods=365), "category": ["A", "B", "C"] * 122 + ["A"], "region": ["North", "South", "East", "West"] * 91 + ["North"], "value": [i + (i % 30) * 10 for i in range(365)] })

app.layout = html.Div([ html.H1("Multi-Input Dashboard"),

html.Div([
    html.Div([
        html.Label("Category"),
        dcc.Dropdown(
            id="category-filter",
            options=[{"label": c, "value": c} for c in df["category"].unique()],
            value=["A", "B", "C"],
            multi=True
        )
    ], style={"width": "45%", "display": "inline-block"}),

    html.Div([
        html.Label("Region"),
        dcc.Dropdown(
            id="region-filter",
            options=[{"label": r, "value": r} for r in df["region"].unique()],
            value=["North", "South", "East", "West"],
            multi=True
        )
    ], style={"width": "45%", "display": "inline-block", "marginLeft": "5%"})
]),

html.Div([
    html.Div([
        dcc.Graph(id="trend-chart")
    ], style={"width": "60%", "display": "inline-block"}),

    html.Div([
        dcc.Graph(id="pie-chart")
    ], style={"width": "38%", "display": "inline-block", "marginLeft": "2%"})
]),

html.Div(id="summary-stats")

])

@callback( [Output("trend-chart", "figure"), Output("pie-chart", "figure"), Output("summary-stats", "children")], [Input("category-filter", "value"), Input("region-filter", "value")] ) def update_all(categories, regions): # Filter data filtered = df[ (df["category"].isin(categories)) & (df["region"].isin(regions)) ]

# Trend chart
trend = filtered.groupby("date")["value"].sum().reset_index()
trend_fig = px.line(trend, x="date", y="value", title="Value Trend")

# Pie chart
by_category = filtered.groupby("category")["value"].sum().reset_index()
pie_fig = px.pie(by_category, values="value", names="category", title="By Category")

# Summary stats
stats = html.Div([
    html.H4("Summary Statistics"),
    html.P(f"Total records: {len(filtered):,}"),
    html.P(f"Total value: {filtered['value'].sum():,}"),
    html.P(f"Average value: {filtered['value'].mean():.2f}")
])

return trend_fig, pie_fig, stats

if name == "main": app.run(debug=True)

Chained Callbacks:

from dash import Dash, html, dcc, callback, Output, Input import pandas as pd

app = Dash(name)

Hierarchical data

data = { "USA": {"California": ["San Francisco", "Los Angeles"], "Texas": ["Houston", "Dallas"]}, "Canada": {"Ontario": ["Toronto", "Ottawa"], "Quebec": ["Montreal", "Quebec City"]} }

app.layout = html.Div([ html.H1("Chained Dropdowns"),

html.Label("Country"),
dcc.Dropdown(id="country-dropdown"),

html.Label("State/Province"),
dcc.Dropdown(id="state-dropdown"),

html.Label("City"),
dcc.Dropdown(id="city-dropdown"),

html.Div(id="selection-output")

])

Populate country dropdown

@callback( Output("country-dropdown", "options"), Input("country-dropdown", "id") # Dummy input to trigger on load ) def set_countries(_): return [{"label": c, "value": c} for c in data.keys()]

Update state options based on country

@callback( Output("state-dropdown", "options"), Output("state-dropdown", "value"), Input("country-dropdown", "value") ) def set_states(country): if country is None: return [], None states = data.get(country, {}).keys() return [{"label": s, "value": s} for s in states], None

Update city options based on state

@callback( Output("city-dropdown", "options"), Output("city-dropdown", "value"), Input("country-dropdown", "value"), Input("state-dropdown", "value") ) def set_cities(country, state): if country is None or state is None: return [], None cities = data.get(country, {}).get(state, []) return [{"label": c, "value": c} for c in cities], None

Display selection

@callback( Output("selection-output", "children"), Input("country-dropdown", "value"), Input("state-dropdown", "value"), Input("city-dropdown", "value") ) def display_selection(country, state, city): return f"Selected: {country or '-'} > {state or '-'} > {city or '-'}"

if name == "main": app.run(debug=True)

  1. Layout Components

HTML Components:

from dash import html

Text elements

layout = html.Div([ html.H1("Main Title"), html.H2("Subtitle"), html.H3("Section Header"), html.P("Paragraph text with ", html.Strong("bold"), " and ", html.Em("italic")), html.Hr(), # Horizontal rule html.Br(), # Line break

# Lists
html.Ul([
    html.Li("Item 1"),
    html.Li("Item 2"),
    html.Li("Item 3")
]),

# Links
html.A("Click here", href="https://example.com", target="_blank"),

# Images
html.Img(src="/assets/logo.png", style={"width": "200px"}),

# Tables
html.Table([
    html.Thead([
        html.Tr([html.Th("Name"), html.Th("Value")])
    ]),
    html.Tbody([
        html.Tr([html.Td("Item 1"), html.Td("100")]),
        html.Tr([html.Td("Item 2"), html.Td("200")])
    ])
])

])

Core Components (dcc):

from dash import dcc

Input components

components = html.Div([ # Dropdown dcc.Dropdown( id="dropdown", options=[ {"label": "Option A", "value": "a"}, {"label": "Option B", "value": "b"}, {"label": "Option C", "value": "c", "disabled": True} ], value="a", multi=False, clearable=True, searchable=True, placeholder="Select..." ),

# Multi-select dropdown
dcc.Dropdown(
    id="multi-dropdown",
    options=[{"label": f"Option {i}", "value": i} for i in range(10)],
    value=[1, 2, 3],
    multi=True
),

# Slider
dcc.Slider(
    id="slider",
    min=0,
    max=100,
    step=5,
    value=50,
    marks={0: "0", 25: "25", 50: "50", 75: "75", 100: "100"}
),

# Range slider
dcc.RangeSlider(
    id="range-slider",
    min=0,
    max=100,
    step=1,
    value=[20, 80],
    marks={i: str(i) for i in range(0, 101, 20)}
),

# Input
dcc.Input(
    id="text-input",
    type="text",
    placeholder="Enter text...",
    debounce=True  # Wait for typing to stop
),

# Textarea
dcc.Textarea(
    id="textarea",
    placeholder="Enter longer text...",
    style={"width": "100%", "height": "100px"}
),

# Checklist
dcc.Checklist(
    id="checklist",
    options=[
        {"label": "Option 1", "value": "1"},
        {"label": "Option 2", "value": "2"},
        {"label": "Option 3", "value": "3"}
    ],
    value=["1"],
    inline=True
),

# Radio items
dcc.RadioItems(
    id="radio",
    options=[
        {"label": "Small", "value": "s"},
        {"label": "Medium", "value": "m"},
        {"label": "Large", "value": "l"}
    ],
    value="m",
    inline=True
),

# Date picker
dcc.DatePickerSingle(
    id="date-picker",
    date="2025-01-01",
    display_format="YYYY-MM-DD"
),

# Date range picker
dcc.DatePickerRange(
    id="date-range",
    start_date="2025-01-01",
    end_date="2025-12-31",
    display_format="YYYY-MM-DD"
),

# Upload
dcc.Upload(
    id="upload",
    children=html.Div(["Drag and Drop or ", html.A("Select Files")]),
    style={
        "width": "100%",
        "height": "60px",
        "lineHeight": "60px",
        "borderWidth": "1px",
        "borderStyle": "dashed",
        "borderRadius": "5px",
        "textAlign": "center"
    }
),

# Tabs
dcc.Tabs(id="tabs", value="tab-1", children=[
    dcc.Tab(label="Tab 1", value="tab-1"),
    dcc.Tab(label="Tab 2", value="tab-2")
]),

# Loading indicator
dcc.Loading(
    id="loading",
    type="default",  # default, graph, cube, circle, dot
    children=html.Div(id="loading-output")
),

# Interval (for periodic updates)
dcc.Interval(
    id="interval-component",
    interval=1000,  # milliseconds
    n_intervals=0
),

# Store (client-side data storage)
dcc.Store(id="data-store", storage_type="session"),  # memory, session, local

# Graph
dcc.Graph(
    id="graph",
    config={
        "displayModeBar": True,
        "displaylogo": False,
        "modeBarButtonsToRemove": ["lasso2d", "select2d"]
    }
)

])

  1. Bootstrap Components

Using Dash Bootstrap Components:

from dash import Dash, html, dcc, callback, Output, Input import dash_bootstrap_components as dbc import plotly.express as px import pandas as pd

Initialize with Bootstrap theme

app = Dash(name, external_stylesheets=[dbc.themes.BOOTSTRAP])

Sample data

df = pd.DataFrame({ "date": pd.date_range("2025-01-01", periods=100), "sales": [100 + i * 2 + (i % 7) * 10 for i in range(100)], "orders": [50 + i + (i % 5) * 5 for i in range(100)] })

Layout with Bootstrap components

app.layout = dbc.Container([ # Header dbc.Row([ dbc.Col([ html.H1("Sales Dashboard", className="text-primary"), html.P("Interactive analytics powered by Dash", className="lead") ]) ], className="mb-4"),

# Metrics row
dbc.Row([
    dbc.Col([
        dbc.Card([
            dbc.CardBody([
                html.H4("Total Sales", className="card-title"),
                html.H2(f"${df['sales'].sum():,}", className="text-success")
            ])
        ])
    ], md=4),
    dbc.Col([
        dbc.Card([
            dbc.CardBody([
                html.H4("Total Orders", className="card-title"),
                html.H2(f"{df['orders'].sum():,}", className="text-info")
            ])
        ])
    ], md=4),
    dbc.Col([
        dbc.Card([
            dbc.CardBody([
                html.H4("Avg Order Value", className="card-title"),
                html.H2(f"${df['sales'].sum() / df['orders'].sum():.2f}", className="text-warning")
            ])
        ])
    ], md=4)
], className="mb-4"),

# Filters
dbc.Row([
    dbc.Col([
        dbc.Card([
            dbc.CardHeader("Filters"),
            dbc.CardBody([
                dbc.Label("Date Range"),
                dcc.DatePickerRange(
                    id="date-range",
                    start_date=df["date"].min(),
                    end_date=df["date"].max(),
                    className="mb-3"
                ),
                dbc.Label("Metric"),
                dcc.Dropdown(
                    id="metric-dropdown",
                    options=[
                        {"label": "Sales", "value": "sales"},
                        {"label": "Orders", "value": "orders"}
                    ],
                    value="sales"
                )
            ])
        ])
    ], md=3),
    dbc.Col([
        dcc.Graph(id="main-chart")
    ], md=9)
]),

# Tabs
dbc.Row([
    dbc.Col([
        dbc.Tabs([
            dbc.Tab(label="Daily Data", tab_id="daily"),
            dbc.Tab(label="Summary", tab_id="summary")
        ], id="tabs", active_tab="daily"),
        html.Div(id="tab-content", className="mt-3")
    ])
], className="mt-4")

], fluid=True)

@callback( Output("main-chart", "figure"), [Input("date-range", "start_date"), Input("date-range", "end_date"), Input("metric-dropdown", "value")] ) def update_chart(start_date, end_date, metric): filtered = df[ (df["date"] >= start_date) & (df["date"] <= end_date) ]

fig = px.line(
    filtered,
    x="date",
    y=metric,
    title=f"{metric.title()} Over Time"
)
fig.update_layout(template="plotly_white")

return fig

@callback( Output("tab-content", "children"), Input("tabs", "active_tab") ) def render_tab(tab): if tab == "daily": return dbc.Table.from_dataframe( df.tail(10), striped=True, bordered=True, hover=True ) elif tab == "summary": return html.Div([ html.P(f"Total Records: {len(df)}"), html.P(f"Date Range: {df['date'].min()} to {df['date'].max()}"), html.P(f"Sales Range: ${df['sales'].min()} - ${df['sales'].max()}") ])

if name == "main": app.run(debug=True)

  1. Multi-Page Applications

Project Structure:

my_dash_app/ ├── app.py # Main entry point ├── pages/ │ ├── init.py │ ├── home.py │ ├── analytics.py │ └── settings.py ├── components/ │ ├── init.py │ ├── navbar.py │ └── footer.py ├── utils/ │ ├── init.py │ └── data.py └── assets/ ├── style.css └── logo.png

Main App (app.py):

from dash import Dash, html, dcc, page_container import dash_bootstrap_components as dbc

app = Dash( name, use_pages=True, external_stylesheets=[dbc.themes.BOOTSTRAP] )

Navbar

navbar = dbc.NavbarSimple( children=[ dbc.NavItem(dbc.NavLink("Home", href="/")), dbc.NavItem(dbc.NavLink("Analytics", href="/analytics")), dbc.NavItem(dbc.NavLink("Settings", href="/settings")), ], brand="My Dashboard", brand_href="/", color="primary", dark=True, )

Layout with navigation and page container

app.layout = html.Div([ navbar, dbc.Container([ page_container ], fluid=True, className="mt-4") ])

if name == "main": app.run(debug=True)

Home Page (pages/home.py):

from dash import html, register_page import dash_bootstrap_components as dbc

register_page(name, path="/", name="Home")

layout = dbc.Container([ dbc.Row([ dbc.Col([ html.H1("Welcome to the Dashboard"), html.P("Select a page from the navigation bar to get started."), dbc.Card([ dbc.CardBody([ html.H4("Quick Links"), dbc.ListGroup([ dbc.ListGroupItem("Analytics", href="/analytics"), dbc.ListGroupItem("Settings", href="/settings") ]) ]) ]) ]) ]) ])

Analytics Page (pages/analytics.py):

from dash import html, dcc, callback, Output, Input, register_page import dash_bootstrap_components as dbc import plotly.express as px import pandas as pd

register_page(name, path="/analytics", name="Analytics")

Generate sample data

df = pd.DataFrame({ "date": pd.date_range("2025-01-01", periods=365), "value": [100 + i + (i % 30) * 5 for i in range(365)] })

layout = dbc.Container([ html.H1("Analytics"),

dbc.Row([
    dbc.Col([
        dbc.Label("Chart Type"),
        dcc.Dropdown(
            id="chart-type",
            options=[
                {"label": "Line", "value": "line"},
                {"label": "Bar", "value": "bar"},
                {"label": "Area", "value": "area"}
            ],
            value="line"
        )
    ], md=4)
], className="mb-4"),

dcc.Graph(id="analytics-chart")

])

@callback( Output("analytics-chart", "figure"), Input("chart-type", "value") ) def update_chart(chart_type): if chart_type == "line": fig = px.line(df, x="date", y="value") elif chart_type == "bar": monthly = df.resample("M", on="date")["value"].sum().reset_index() fig = px.bar(monthly, x="date", y="value") else: fig = px.area(df, x="date", y="value")

return fig

6. Authentication

Basic Authentication:

from dash import Dash, html, dcc import dash_auth

app = Dash(name)

Basic authentication

VALID_USERNAME_PASSWORD_PAIRS = { "admin": "admin123", "user": "user123" }

auth = dash_auth.BasicAuth( app, VALID_USERNAME_PASSWORD_PAIRS )

app.layout = html.Div([ html.H1("Protected Dashboard"), html.P("You are authenticated!") ])

if name == "main": app.run(debug=True)

Custom Login (with session):

from dash import Dash, html, dcc, callback, Output, Input, State import dash_bootstrap_components as dbc from flask import session

app = Dash(name, external_stylesheets=[dbc.themes.BOOTSTRAP]) app.server.secret_key = "your-secret-key-here"

Login form

login_form = dbc.Card([ dbc.CardBody([ html.H4("Login"), dbc.Input(id="username", placeholder="Username", className="mb-2"), dbc.Input(id="password", type="password", placeholder="Password", className="mb-2"), dbc.Button("Login", id="login-btn", color="primary"), html.Div(id="login-message") ]) ], style={"maxWidth": "400px", "margin": "100px auto"})

Main content

main_content = html.Div([ html.H1("Dashboard"), html.P("Welcome! You are logged in."), dbc.Button("Logout", id="logout-btn", color="secondary") ])

app.layout = html.Div([ dcc.Location(id="url"), html.Div(id="page-content") ])

@callback( Output("page-content", "children"), Input("url", "pathname") ) def display_page(pathname): if session.get("authenticated"): return main_content return login_form

@callback( [Output("login-message", "children"), Output("url", "pathname")], Input("login-btn", "n_clicks"), [State("username", "value"), State("password", "value")], prevent_initial_call=True ) def login(n_clicks, username, password): # Simple validation (use proper auth in production) if username == "admin" and password == "admin123": session["authenticated"] = True return "", "/" return dbc.Alert("Invalid credentials", color="danger"), "/"

@callback( Output("url", "pathname", allow_duplicate=True), Input("logout-btn", "n_clicks"), prevent_initial_call=True ) def logout(n_clicks): session.clear() return "/"

if name == "main": app.run(debug=True)

Complete Examples

Example 1: Sales Analytics Dashboard

from dash import Dash, html, dcc, callback, Output, Input import dash_bootstrap_components as dbc import plotly.express as px import plotly.graph_objects as go from plotly.subplots import make_subplots import pandas as pd import numpy as np from datetime import datetime, timedelta

Initialize app

app = Dash(name, external_stylesheets=[dbc.themes.FLATLY])

Generate sample data

np.random.seed(42) dates = pd.date_range("2024-01-01", "2025-12-31", freq="D") n_days = len(dates)

df = pd.DataFrame({ "date": dates, "revenue": np.cumsum(np.random.randn(n_days) * 100 + 500), "orders": np.random.poisson(100, n_days), "customers": np.random.poisson(80, n_days), "region": np.random.choice(["North", "South", "East", "West"], n_days), "category": np.random.choice(["Electronics", "Clothing", "Food", "Home"], n_days) })

Calculate previous period metrics

current_revenue = df[df["date"] >= "2025-01-01"]["revenue"].sum() prev_revenue = df[df["date"] < "2025-01-01"]["revenue"].sum() revenue_change = ((current_revenue - prev_revenue) / prev_revenue * 100)

Layout

app.layout = dbc.Container([ # Header dbc.Row([ dbc.Col([ html.H1("Sales Analytics Dashboard", className="text-primary mb-0"), html.P(f"Last updated: {datetime.now().strftime('%Y-%m-%d %H:%M')}", className="text-muted") ], md=8), dbc.Col([ dbc.ButtonGroup([ dbc.Button("Export", outline=True, color="primary"), dbc.Button("Refresh", outline=True, color="secondary") ]) ], md=4, className="text-end") ], className="mb-4 mt-3"),

# Date filter
dbc.Row([
    dbc.Col([
        dbc.Card([
            dbc.CardBody([
                dbc.Row([
                    dbc.Col([
                        dbc.Label("Date Range"),
                        dcc.DatePickerRange(
                            id="date-filter",
                            start_date="2025-01-01",
                            end_date="2025-12-31",
                            display_format="YYYY-MM-DD"
                        )
                    ], md=4),
                    dbc.Col([
                        dbc.Label("Region"),
                        dcc.Dropdown(
                            id="region-filter",
                            options=[{"label": r, "value": r} for r in df["region"].unique()],
                            value=df["region"].unique().tolist(),
                            multi=True
                        )
                    ], md=4),
                    dbc.Col([
                        dbc.Label("Category"),
                        dcc.Dropdown(
                            id="category-filter",
                            options=[{"label": c, "value": c} for c in df["category"].unique()],
                            value=df["category"].unique().tolist(),
                            multi=True
                        )
                    ], md=4)
                ])
            ])
        ])
    ])
], className="mb-4"),

# KPI Cards
dbc.Row([
    dbc.Col([
        dbc.Card([
            dbc.CardBody([
                html.H6("Total Revenue", className="text-muted"),
                html.H3(id="kpi-revenue", className="text-success"),
                html.Small(id="kpi-revenue-change", className="text-muted")
            ])
        ], color="light")
    ], md=3),
    dbc.Col([
        dbc.Card([
            dbc.CardBody([
                html.H6("Total Orders", className="text-muted"),
                html.H3(id="kpi-orders", className="text-info"),
                html.Small(id="kpi-orders-change", className="text-muted")
            ])
        ], color="light")
    ], md=3),
    dbc.Col([
        dbc.Card([
            dbc.CardBody([
                html.H6("Unique Customers", className="text-muted"),
                html.H3(id="kpi-customers", className="text-warning"),
                html.Small(id="kpi-customers-change", className="text-muted")
            ])
        ], color="light")
    ], md=3),
    dbc.Col([
        dbc.Card([
            dbc.CardBody([
                html.H6("Avg Order Value", className="text-muted"),
                html.H3(id="kpi-aov", className="text-primary"),
                html.Small(id="kpi-aov-change", className="text-muted")
            ])
        ], color="light")
    ], md=3)
], className="mb-4"),

# Charts Row 1
dbc.Row([
    dbc.Col([
        dbc.Card([
            dbc.CardHeader("Revenue Trend"),
            dbc.CardBody([
                dcc.Graph(id="revenue-trend")
            ])
        ])
    ], md=8),
    dbc.Col([
        dbc.Card([
            dbc.CardHeader("Revenue by Category"),
            dbc.CardBody([
                dcc.Graph(id="category-pie")
            ])
        ])
    ], md=4)
], className="mb-4"),

# Charts Row 2
dbc.Row([
    dbc.Col([
        dbc.Card([
            dbc.CardHeader("Regional Performance"),
            dbc.CardBody([
                dcc.Graph(id="regional-bar")
            ])
        ])
    ], md=6),
    dbc.Col([
        dbc.Card([
            dbc.CardHeader("Orders vs Customers"),
            dbc.CardBody([
                dcc.Graph(id="scatter-chart")
            ])
        ])
    ], md=6)
], className="mb-4"),

# Data Table
dbc.Row([
    dbc.Col([
        dbc.Card([
            dbc.CardHeader("Detailed Data"),
            dbc.CardBody([
                html.Div(id="data-table")
            ])
        ])
    ])
])

], fluid=True)

Callbacks

@callback( [Output("kpi-revenue", "children"), Output("kpi-orders", "children"), Output("kpi-customers", "children"), Output("kpi-aov", "children"), Output("revenue-trend", "figure"), Output("category-pie", "figure"), Output("regional-bar", "figure"), Output("scatter-chart", "figure"), Output("data-table", "children")], [Input("date-filter", "start_date"), Input("date-filter", "end_date"), Input("region-filter", "value"), Input("category-filter", "value")] ) def update_dashboard(start_date, end_date, regions, categories): # Filter data filtered = df[ (df["date"] >= start_date) & (df["date"] <= end_date) & (df["region"].isin(regions)) & (df["category"].isin(categories)) ]

# KPIs
revenue = f"${filtered['revenue'].sum():,.0f}"
orders = f"{filtered['orders'].sum():,}"
customers = f"{filtered['customers'].sum():,}"
aov = f"${filtered['revenue'].sum() / filtered['orders'].sum():.2f}" if filtered['orders'].sum() > 0 else "$0"

# Revenue trend
daily_revenue = filtered.groupby("date")["revenue"].sum().reset_index()
trend_fig = px.line(
    daily_revenue,
    x="date",
    y="revenue",
    title=None
)
trend_fig.update_layout(
    margin=dict(l=0, r=0, t=0, b=0),
    hovermode="x unified"
)

# Category pie
by_category = filtered.groupby("category")["revenue"].sum().reset_index()
pie_fig = px.pie(
    by_category,
    values="revenue",
    names="category",
    title=None
)
pie_fig.update_layout(margin=dict(l=0, r=0, t=0, b=0))

# Regional bar
by_region = filtered.groupby("region").agg({
    "revenue": "sum",
    "orders": "sum"
}).reset_index()
bar_fig = px.bar(
    by_region,
    x="region",
    y="revenue",
    color="region",
    title=None
)
bar_fig.update_layout(
    margin=dict(l=0, r=0, t=0, b=0),
    showlegend=False
)

# Scatter
scatter_fig = px.scatter(
    filtered.groupby("date").agg({"orders": "sum", "customers": "sum"}).reset_index(),
    x="orders",
    y="customers",
    title=None,
    trendline="ols"
)
scatter_fig.update_layout(margin=dict(l=0, r=0, t=0, b=0))

# Table
table = dbc.Table.from_dataframe(
    filtered.groupby(["region", "category"]).agg({
        "revenue": "sum",
        "orders": "sum",
        "customers": "sum"
    }).reset_index().round(2),
    striped=True,
    bordered=True,
    hover=True,
    responsive=True
)

return revenue, orders, customers, aov, trend_fig, pie_fig, bar_fig, scatter_fig, table

if name == "main": app.run(debug=True)

Example 2: Real-Time Monitoring Dashboard

from dash import Dash, html, dcc, callback, Output, Input import dash_bootstrap_components as dbc import plotly.graph_objects as go from collections import deque import random from datetime import datetime

app = Dash(name, external_stylesheets=[dbc.themes.CYBORG])

Initialize data stores

MAX_POINTS = 50 time_data = deque(maxlen=MAX_POINTS) cpu_data = deque(maxlen=MAX_POINTS) memory_data = deque(maxlen=MAX_POINTS) network_data = deque(maxlen=MAX_POINTS)

Layout

app.layout = dbc.Container([ html.H1("Real-Time System Monitor", className="text-center my-4"),

# Status indicators
dbc.Row([
    dbc.Col([
        dbc.Card([
            dbc.CardBody([
                html.H6("CPU Usage"),
                html.H2(id="cpu-value", className="text-info"),
                dbc.Progress(id="cpu-progress", value=0, max=100)
            ])
        ])
    ], md=4),
    dbc.Col([
        dbc.Card([
            dbc.CardBody([
                html.H6("Memory Usage"),
                html.H2(id="memory-value", className="text-warning"),
                dbc.Progress(id="memory-progress", value=0, max=100)
            ])
        ])
    ], md=4),
    dbc.Col([
        dbc.Card([
            dbc.CardBody([
                html.H6("Network I/O"),
                html.H2(id="network-value", className="text-success"),
                dbc.Progress(id="network-progress", value=0, max=100)
            ])
        ])
    ], md=4)
], className="mb-4"),

# Charts
dbc.Row([
    dbc.Col([
        dbc.Card([
            dbc.CardHeader("System Metrics (Last 50 Updates)"),
            dbc.CardBody([
                dcc.Graph(id="live-graph", animate=True)
            ])
        ])
    ])
]),

# Interval component for updates
dcc.Interval(
    id="interval-component",
    interval=1000,  # 1 second
    n_intervals=0
)

], fluid=True)

@callback( [Output("cpu-value", "children"), Output("memory-value", "children"), Output("network-value", "children"), Output("cpu-progress", "value"), Output("memory-progress", "value"), Output("network-progress", "value"), Output("live-graph", "figure")], Input("interval-component", "n_intervals") ) def update_metrics(n): # Simulate metrics cpu = random.uniform(20, 80) memory = random.uniform(40, 90) network = random.uniform(10, 60)

# Update data stores
time_data.append(datetime.now())
cpu_data.append(cpu)
memory_data.append(memory)
network_data.append(network)

# Create figure
fig = go.Figure()

fig.add_trace(go.Scatter(
    x=list(time_data),
    y=list(cpu_data),
    name="CPU",
    mode="lines",
    line=dict(color="#17a2b8")
))

fig.add_trace(go.Scatter(
    x=list(time_data),
    y=list(memory_data),
    name="Memory",
    mode="lines",
    line=dict(color="#ffc107")
))

fig.add_trace(go.Scatter(
    x=list(time_data),
    y=list(network_data),
    name="Network",
    mode="lines",
    line=dict(color="#28a745")
))

fig.update_layout(
    template="plotly_dark",
    paper_bgcolor="rgba(0,0,0,0)",
    plot_bgcolor="rgba(0,0,0,0)",
    yaxis=dict(range=[0, 100], title="Usage %"),
    xaxis=dict(title="Time"),
    legend=dict(orientation="h", yanchor="bottom", y=1.02),
    margin=dict(l=50, r=20, t=30, b=50),
    uirevision="constant"  # Preserve zoom/pan on update
)

return (
    f"{cpu:.1f}%",
    f"{memory:.1f}%",
    f"{network:.1f}%",
    cpu,
    memory,
    network,
    fig
)

if name == "main": app.run(debug=True)

Example 3: Data Table with AG Grid

from dash import Dash, html, callback, Output, Input import dash_ag_grid as dag import dash_bootstrap_components as dbc import pandas as pd import numpy as np

app = Dash(name, external_stylesheets=[dbc.themes.BOOTSTRAP])

Generate sample data

np.random.seed(42) df = pd.DataFrame({ "ID": range(1, 1001), "Name": [f"Product {i}" for i in range(1, 1001)], "Category": np.random.choice(["Electronics", "Clothing", "Food", "Home"], 1000), "Price": np.random.uniform(10, 500, 1000).round(2), "Stock": np.random.randint(0, 100, 1000), "Rating": np.random.uniform(1, 5, 1000).round(1), "Last Updated": pd.date_range("2025-01-01", periods=1000, freq="H") })

Column definitions

column_defs = [ {"field": "ID", "filter": "agNumberColumnFilter", "width": 80}, {"field": "Name", "filter": "agTextColumnFilter"}, { "field": "Category", "filter": "agSetColumnFilter", "cellStyle": {"fontWeight": "bold"} }, { "field": "Price", "filter": "agNumberColumnFilter", "valueFormatter": {"function": "'$' + params.value.toFixed(2)"}, "cellStyle": { "function": "params.value > 300 ? {'color': 'red'} : {'color': 'green'}" } }, { "field": "Stock", "filter": "agNumberColumnFilter", "cellStyle": { "function": "params.value < 10 ? {'backgroundColor': '#ffcccc'} : {}" } }, { "field": "Rating", "filter": "agNumberColumnFilter", "cellRenderer": "agSparklineCellRenderer", "cellRendererParams": { "sparklineOptions": { "type": "bar", "fill": "#5470c6" } } }, { "field": "Last Updated", "filter": "agDateColumnFilter", "valueFormatter": {"function": "new Date(params.value).toLocaleDateString()"} } ]

Layout

app.layout = dbc.Container([ html.H1("Product Inventory", className="my-4"),

dbc.Row([
    dbc.Col([
        dbc.Input(
            id="search-input",
            placeholder="Quick search...",
            className="mb-3"
        )
    ], md=4),
    dbc.Col([
        dbc.Button("Export CSV", id="export-btn", color="primary")
    ], md=2)
]),

dag.AgGrid(
    id="inventory-grid",
    columnDefs=column_defs,
    rowData=df.to_dict("records"),
    defaultColDef={
        "sortable": True,
        "filter": True,
        "resizable": True,
        "floatingFilter": True
    },
    dashGridOptions={
        "pagination": True,
        "paginationPageSize": 20,
        "rowSelection": "multiple",
        "animateRows": True
    },
    style={"height": "600px"}
),

html.Div(id="selection-output", className="mt-3")

], fluid=True)

@callback( Output("inventory-grid", "dashGridOptions"), Input("search-input", "value") ) def update_search(search_value): return { "pagination": True, "paginationPageSize": 20, "rowSelection": "multiple", "animateRows": True, "quickFilterText": search_value }

@callback( Output("selection-output", "children"), Input("inventory-grid", "selectedRows") ) def display_selection(selected): if selected: return dbc.Alert( f"Selected {len(selected)} items. Total value: ${sum(r['Price'] for r in selected):,.2f}", color="info" ) return ""

if name == "main": app.run(debug=True)

Deployment Patterns

Gunicorn Production Server

wsgi.py

from app import app

server = app.server

if name == "main": server.run()

Run with Gunicorn

gunicorn wsgi:server -b 0.0.0.0:8050 -w 4

Docker Deployment

Dockerfile

FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8050

CMD ["gunicorn", "wsgi:server", "-b", "0.0.0.0:8050", "-w", "4"]

docker-compose.yml

version: "3.8" services: dash: build: . ports: - "8050:8050" environment: - DASH_DEBUG=false restart: unless-stopped

Cloud Deployment (Heroku)

Procfile

web: gunicorn wsgi:server

requirements.txt

dash>=2.14.0 dash-bootstrap-components>=1.5.0 plotly>=5.18.0 pandas>=2.0.0 gunicorn>=21.0.0

Best Practices

  1. Optimize Callback Performance

Use prevent_initial_call when appropriate

@callback( Output("output", "children"), Input("button", "n_clicks"), prevent_initial_call=True ) def handle_click(n_clicks): return f"Clicked {n_clicks} times"

Use State for non-triggering inputs

@callback( Output("output", "children"), Input("submit-btn", "n_clicks"), State("input-field", "value") # Doesn't trigger callback ) def submit_form(n_clicks, value): return f"Submitted: {value}"

  1. Efficient Data Loading

Cache expensive computations

from flask_caching import Cache

cache = Cache(app.server, config={"CACHE_TYPE": "simple"})

@cache.memoize(timeout=300) def load_data(): return pd.read_parquet("large_file.parquet")

  1. Modular Callbacks

Separate callbacks into modules

callbacks/analytics.py

from dash import callback, Output, Input

def register_callbacks(app): @callback( Output("chart", "figure"), Input("dropdown", "value") ) def update_chart(value): return create_figure(value)

  1. Error Handling

from dash import callback, Output, Input from dash.exceptions import PreventUpdate

@callback( Output("output", "children"), Input("input", "value") ) def safe_callback(value): if value is None: raise PreventUpdate

try:
    result = process(value)
    return result
except Exception as e:
    return html.Div(f"Error: {str(e)}", className="text-danger")

Troubleshooting

Common Issues

Issue: Callback not firing

Check component IDs match exactly

Verify Input/Output/State decorators

Check for circular dependencies

Issue: Slow initial load

Use loading states

dcc.Loading( children=[dcc.Graph(id="graph")], type="circle" )

Issue: Memory leaks

Clear caches periodically

Use background callbacks for long operations

Limit data in client-side stores

Issue: Multiple callback outputs

Use allow_duplicate=True for same output

@callback( Output("output", "children", allow_duplicate=True), Input("button2", "n_clicks"), prevent_initial_call=True )

Version History

  • 1.0.0 (2026-01-17): Initial release

  • Core application structure

  • Callbacks and interactivity

  • Layout components (HTML, DCC, Bootstrap)

  • Multi-page applications

  • Authentication patterns

  • Complete dashboard examples

  • Real-time monitoring example

  • AG Grid integration

  • Deployment patterns

  • Best practices and troubleshooting

Resources

Build enterprise-grade interactive dashboards with Python and Plotly!

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

echarts

No summary provided by upstream source.

Repository SourceNeeds Review
General

pandoc

No summary provided by upstream source.

Repository SourceNeeds Review
General

mkdocs

No summary provided by upstream source.

Repository SourceNeeds Review
General

gis

No summary provided by upstream source.

Repository SourceNeeds Review