Streamlit Sales Dashboard: A Practical Tutorial

AlexMaster Advanced 5h ago Updated Jul 25, 2026 192 views 10 likes 2 min read

Streamlit is probably the fastest way to turn a Python script into a functional web app without touching a single line of CSS or JavaScript. I've used it for several internal tools because it handles the frontend state management automatically, allowing you to focus entirely on the data logic.

Here is a breakdown of how to build a production-ready sales analytics dashboard with filtering and KPI tracking.

Prerequisites

You'll need Python 3.9+. Install the core stack via pip:

pip install streamlit pandas numpy

1. Data Setup and Performance Caching

The key to a responsive Streamlit app is @st.cache_data. Without it, the app reruns the entire script (including heavy data loading) every time a user clicks a filter.

import streamlit as st
import pandas as pd
import numpy as np

# Set layout configuration
st.set_page_config(page_title="Sales Dashboard", layout="wide")

# Cache data loading for performance optimization
@st.cache_data
def load_data():
 dates = pd.date_range("2025-01-01", periods=180)
 regions = ["North", "South", "East", "West"]
 df = pd.DataFrame({
 "date": np.random.choice(dates, 500),
 "region": np.random.choice(regions, 500),
 "product": np.random.choice(["A", "B", "C"], 500),
 "sales": np.random.randint(100, 5000, 500),
 "units": np.random.randint(1, 50, 500),
 })
 return df.sort_values("date")

df = load_data()

2. Implementing Dynamic Filters

I prefer placing filters in the sidebar to maximize the screen real estate for charts. Using a boolean mask is the most efficient way to handle multi-select filtering in Pandas.

# --- Sidebar filters ---
st.sidebar.header("Filters")
region_filter = st.sidebar.multiselect("Region", df["region"].unique(), default=df["region"].unique())
product_filter = st.sidebar.multiselect("Product", df["product"].unique(), default=df["product"].unique())
date_range = st.sidebar.date_input("Date range", [df["date"].min(), df["date"].max()])

# Filter dataframe based on selections
mask = (
 df["region"].isin(region_filter)
 & df["product"].isin(product_filter)
 & (df["date"] >= pd.to_datetime(date_range[0]))
 & (df["date"] <= pd.to_datetime(date_range[1]))
)
filtered = df[mask]

3. Building the KPI Layer and Visuals

To create a professional "Executive" view, use st.columns for KPIs and st.expander for the raw data table so it doesn't clutter the UI.

# --- Title & Subtitle ---
st.title("📈 Sales Dashboard")
st.caption(f"Showing {len(filtered):,} records")

# --- KPI row ---
c1, c2, c3, c4 = st.columns(4)
c1.metric("Total Sales", f"${filtered['sales'].sum():,.0f}")
c2.metric("Total Units", f"{filtered['units'].sum():,}")
c3.metric("Avg Order", f"${filtered['sales'].mean():,.0f}" if len(filtered) else "$0")
c4.metric("Orders", f"{len(filtered):,}")

st.divider()

# --- Visualizations ---
col1, col2 = st.columns(2)

with col1:
 st.subheader("Sales Over Time")
 daily = filtered.groupby("date")["sales"].sum()
 st.line_chart(daily)

with col2:
 st.subheader("Sales by Region")
 by_region = filtered.groupby("region")["sales"].sum()
 st.bar_chart(by_region)

# --- Product Performance ---
st.subheader("Sales by Product")
by_product = filtered.groupby("product")["sales"].sum()
st.bar_chart(by_product)

# --- Raw Data Section ---
with st.expander("View raw data"):
 st.dataframe(filtered, use_container_width=True)

To deploy this, just run streamlit run app.py in your terminal. It's a solid AI workflow for anyone needing to prototype a data tool quickly.

AI ProgrammingAI Codingpythonstreamlitdatascience

All Replies (3)

A
AveryPilot Novice 13h ago
Try using st.cache_data for the data loading part, otherwise it reruns every time you click something.
0 Reply
M
MaxOwl Intermediate 13h ago
Does it handle large CSVs well, or does it start lagging once the dataset grows?
0 Reply
A
AlexTinkerer Advanced 13h ago
Used it for a quick prototype last month and it saved me days of frontend work.
0 Reply

Write a Reply

Markdown supported