DEV Community

ROBERTO CARLOS HUAMAN RIVERA
ROBERTO CARLOS HUAMAN RIVERA

Posted on

🚀 Building and Deploying an Interactive Data Dashboard with Streamlit, Plotly and GitHub Actions

Have you ever created a data analysis in Python, generated some charts, and then realized that the only way to show the results was by sending screenshots or a Jupyter Notebook?

For data analysts and developers, visualizing information is only part of the challenge. A good data project should also be interactive, accessible, reproducible, and easy to deploy.

This is where Streamlit becomes extremely useful.

Streamlit is a Python framework that allows developers to transform Python scripts into interactive web applications without needing to build a separate frontend using HTML, CSS, or JavaScript.

In this article, we will build a Sales Analytics Dashboard using Python, Pandas, Plotly, and Streamlit. We will then publish the source code on GitHub, implement automation with GitHub Actions, and deploy the application publicly using Streamlit Community Cloud.


📊 The Project: Sales Analytics Dashboard

Imagine that a company wants to analyze its sales performance.

The company needs a dashboard where users can quickly see:

  • Total revenue
  • Total orders
  • Average order value
  • Revenue by product category
  • Monthly sales trends
  • Sales by region

Instead of generating static charts, we will create an interactive dashboard where users can filter the information and see the visualizations update automatically.

Our technology stack will be:

  • Python – Programming language
  • Pandas – Data processing
  • Plotly – Interactive charts
  • Streamlit – Dashboard interface
  • GitHub – Version control and public repository
  • GitHub Actions – Automation and validation
  • Streamlit Community Cloud – Public deployment

Step 1: Project Structure

Before writing the dashboard, we organize the project.

sales-dashboard/
│
├── .github/
│   └── workflows/
│       └── python-app.yml
│
├── data/
│   └── sales.csv
│
├── app.py
├── requirements.txt
└── README.md
Enter fullscreen mode Exit fullscreen mode

The most important file is app.py, which contains our Streamlit application.

The requirements.txt file contains all Python dependencies required to run the project.

Our requirements.txt looks like this:

streamlit
pandas
plotly
Enter fullscreen mode Exit fullscreen mode

Step 2: Creating the Dataset

For this example, imagine that our sales.csv file contains the following information:

Date,Product,Category,Region,Quantity,Revenue
2026-01-05,Laptop,Technology,North,2,2400
2026-01-10,Headphones,Technology,South,5,750
2026-02-03,Office Chair,Furniture,West,3,900
2026-02-15,Desk,Furniture,East,2,1200
2026-03-01,Smartphone,Technology,North,4,3200
2026-03-20,Notebook,Office Supplies,South,20,200
2026-04-10,Monitor,Technology,West,3,1050
2026-04-22,Printer,Office Supplies,East,2,700
Enter fullscreen mode Exit fullscreen mode

In a real-world project, this dataset could come from a database, API, Excel file, cloud storage service, or business information system.

For this dashboard, we will load the CSV file using Pandas.


Step 3: Building the Streamlit Application

Now we can create the main application.

Create a file named:

app.py
Enter fullscreen mode Exit fullscreen mode

First, import the required libraries:

import streamlit as st
import pandas as pd
import plotly.express as px
Enter fullscreen mode Exit fullscreen mode

Next, configure the Streamlit page:

st.set_page_config(
    page_title="Sales Analytics Dashboard",
    page_icon="📊",
    layout="wide"
)

st.title("📊 Sales Analytics Dashboard")

st.write(
    "Interactive dashboard for analyzing sales performance "
    "by category, region and time."
)
Enter fullscreen mode Exit fullscreen mode

The layout="wide" configuration gives us more horizontal space, which is particularly useful for dashboards.


Step 4: Loading and Preparing the Data

We can load our dataset with Pandas:

@st.cache_data
def load_data():
    df = pd.read_csv("data/sales.csv")
    df["Date"] = pd.to_datetime(df["Date"])
    return df

df = load_data()
Enter fullscreen mode Exit fullscreen mode

The dataset contains sales transactions with information such as date, category, region, quantity, and revenue.

After converting the Date column into a datetime value, we can also create a month field:

df["Month"] = df["Date"].dt.to_period("M").astype(str)
Enter fullscreen mode Exit fullscreen mode

This will allow us to analyze monthly sales trends.


Step 5: Adding Interactive Filters

One of the main advantages of Streamlit is that we can easily add interactive widgets.

For example, users can filter the dashboard by region and product category.

st.sidebar.header("Dashboard Filters")

selected_region = st.sidebar.multiselect(
    "Select Region",
    options=df["Region"].unique(),
    default=df["Region"].unique()
)

selected_category = st.sidebar.multiselect(
    "Select Category",
    options=df["Category"].unique(),
    default=df["Category"].unique()
)
Enter fullscreen mode Exit fullscreen mode

Now we apply these filters to our dataset:

filtered_df = df[
    (df["Region"].isin(selected_region)) &
    (df["Category"].isin(selected_category))
]
Enter fullscreen mode Exit fullscreen mode

Every visualization that uses filtered_df will automatically update when the user changes the filters.


Step 6: Creating KPI Metrics

A dashboard should provide important information immediately.

For this project, we will calculate three Key Performance Indicators:

  • Total Revenue
  • Total Orders
  • Average Order Value
total_revenue = filtered_df["Revenue"].sum()

total_orders = len(filtered_df)

average_order_value = (
    total_revenue / total_orders
    if total_orders > 0
    else 0
)
Enter fullscreen mode Exit fullscreen mode

Then we display them using Streamlit metrics:

col1, col2, col3 = st.columns(3)

col1.metric(
    "💰 Total Revenue",
    f"${total_revenue:,.2f}"
)

col2.metric(
    "🛒 Total Orders",
    total_orders
)

col3.metric(
    "📈 Average Order Value",
    f"${average_order_value:,.2f}"
)
Enter fullscreen mode Exit fullscreen mode

This gives users a quick summary of the current filtered data.


Step 7: Revenue by Category

Now we can create our first visualization.

We group the data by product category:

category_sales = (
    filtered_df.groupby("Category")["Revenue"]
    .sum()
    .reset_index()
)
Enter fullscreen mode Exit fullscreen mode

Then we create an interactive bar chart using Plotly:

fig_category = px.bar(
    category_sales,
    x="Category",
    y="Revenue",
    title="Revenue by Product Category",
    text_auto=True
)

st.plotly_chart(
    fig_category,
    use_container_width=True
)
Enter fullscreen mode Exit fullscreen mode

Users can interact with the Plotly visualization by hovering over bars, zooming, and inspecting individual values.


Step 8: Monthly Sales Trend

Another important business visualization is the evolution of revenue over time.

First, we calculate monthly revenue:

monthly_sales = (
    filtered_df.groupby("Month")["Revenue"]
    .sum()
    .reset_index()
)
Enter fullscreen mode Exit fullscreen mode

Then we generate a line chart:

fig_month = px.line(
    monthly_sales,
    x="Month",
    y="Revenue",
    markers=True,
    title="Monthly Revenue Trend"
)

st.plotly_chart(
    fig_month,
    use_container_width=True
)
Enter fullscreen mode Exit fullscreen mode

This chart helps identify sales growth, reductions, or unusual changes over time.


Step 9: Sales by Region

We can also compare revenue between different geographical regions.

region_sales = (
    filtered_df.groupby("Region")["Revenue"]
    .sum()
    .reset_index()
)
Enter fullscreen mode Exit fullscreen mode

For this visualization, we can use a pie chart:

fig_region = px.pie(
    region_sales,
    names="Region",
    values="Revenue",
    title="Revenue Distribution by Region"
)

st.plotly_chart(
    fig_region,
    use_container_width=True
)
Enter fullscreen mode Exit fullscreen mode

Our dashboard now contains multiple visualization techniques for understanding the same dataset from different perspectives.


Step 10: Displaying the Raw Data

Sometimes users need to inspect the original information.

At the bottom of the application, we can include an expandable section containing the filtered dataset.

with st.expander("View Dataset"):
    st.dataframe(
        filtered_df,
        use_container_width=True
    )
Enter fullscreen mode Exit fullscreen mode

This allows the dashboard to work both as a visualization tool and a simple data exploration interface.


🧩 Complete Application

The final app.py file looks like this:

import streamlit as st
import pandas as pd
import plotly.express as px


st.set_page_config(
    page_title="Sales Analytics Dashboard",
    page_icon="📊",
    layout="wide"
)

st.title("📊 Sales Analytics Dashboard")

st.write(
    "Interactive dashboard for analyzing sales performance "
    "by category, region and time."
)


@st.cache_data
def load_data():
    df = pd.read_csv("data/sales.csv")
    df["Date"] = pd.to_datetime(df["Date"])
    df["Month"] = df["Date"].dt.to_period("M").astype(str)
    return df


df = load_data()


# Sidebar filters

st.sidebar.header("Dashboard Filters")

selected_region = st.sidebar.multiselect(
    "Select Region",
    options=df["Region"].unique(),
    default=df["Region"].unique()
)

selected_category = st.sidebar.multiselect(
    "Select Category",
    options=df["Category"].unique(),
    default=df["Category"].unique()
)


filtered_df = df[
    (df["Region"].isin(selected_region)) &
    (df["Category"].isin(selected_category))
]


# KPIs

total_revenue = filtered_df["Revenue"].sum()
total_orders = len(filtered_df)

average_order_value = (
    total_revenue / total_orders
    if total_orders > 0
    else 0
)

col1, col2, col3 = st.columns(3)

col1.metric(
    "💰 Total Revenue",
    f"${total_revenue:,.2f}"
)

col2.metric(
    "🛒 Total Orders",
    total_orders
)

col3.metric(
    "📈 Average Order Value",
    f"${average_order_value:,.2f}"
)


# Revenue by Category

category_sales = (
    filtered_df.groupby("Category")["Revenue"]
    .sum()
    .reset_index()
)

fig_category = px.bar(
    category_sales,
    x="Category",
    y="Revenue",
    title="Revenue by Product Category",
    text_auto=True
)

st.plotly_chart(
    fig_category,
    use_container_width=True
)


# Monthly Revenue

monthly_sales = (
    filtered_df.groupby("Month")["Revenue"]
    .sum()
    .reset_index()
)

fig_month = px.line(
    monthly_sales,
    x="Month",
    y="Revenue",
    markers=True,
    title="Monthly Revenue Trend"
)

st.plotly_chart(
    fig_month,
    use_container_width=True
)


# Revenue by Region

region_sales = (
    filtered_df.groupby("Region")["Revenue"]
    .sum()
    .reset_index()
)

fig_region = px.pie(
    region_sales,
    names="Region",
    values="Revenue",
    title="Revenue Distribution by Region"
)

st.plotly_chart(
    fig_region,
    use_container_width=True
)


# Dataset

with st.expander("View Dataset"):
    st.dataframe(
        filtered_df,
        use_container_width=True
    )
Enter fullscreen mode Exit fullscreen mode

Running the application locally is extremely simple:

streamlit run app.py
Enter fullscreen mode Exit fullscreen mode

After executing the command, Streamlit starts a local web server where we can test and interact with the dashboard.


Step 11: Publishing the Project on GitHub

A public repository is important because it allows other developers to inspect, reproduce, and improve the project.

After creating a new GitHub repository, we can upload the project using Git:

git init
git add .
git commit -m "Initial Streamlit dashboard"
git branch -M main
git remote add origin https://github.com/YOUR-USERNAME/sales-dashboard.git
git push -u origin main
Enter fullscreen mode Exit fullscreen mode

Step 12: Automation with GitHub Actions

Publishing code is not enough.

We also want an automated process that verifies that the application can be installed and that the Python code is valid whenever changes are pushed to the repository.

For this purpose, we can use GitHub Actions.

Create the following file:

.github/workflows/python-app.yml
Enter fullscreen mode Exit fullscreen mode

Add:

name: Streamlit Dashboard CI

on:
  push:
    branches: ["main"]

  pull_request:
    branches: ["main"]

jobs:

  test-dashboard:

    runs-on: ubuntu-latest

    steps:

      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt

      - name: Check Python syntax
        run: |
          python -m py_compile app.py
Enter fullscreen mode Exit fullscreen mode

Now every push or Pull Request to the main branch automatically executes the workflow.

The workflow performs three important tasks:

  1. Downloads the repository.
  2. Creates the Python environment and installs the dependencies.
  3. Checks that the application does not contain Python syntax errors.

If something is wrong, GitHub Actions marks the workflow as failed.

This provides a simple Continuous Integration (CI) process for our dashboard.


Step 13: Deploying to Streamlit Community Cloud

Now comes the most important part: making the dashboard publicly accessible.

Streamlit Community Cloud can deploy Streamlit applications directly from GitHub.

The deployment process is:

  1. Push the complete application to GitHub.
  2. Sign in to Streamlit Community Cloud.
  3. Connect the GitHub account.
  4. Select the dashboard repository.
  5. Select the main branch.
  6. Specify app.py as the application entry point.
  7. Deploy the application.

The platform installs the dependencies contained in requirements.txt and starts the Streamlit application.

Once deployed, the dashboard receives a public address similar to:

https://your-dashboard.streamlit.app
Enter fullscreen mode Exit fullscreen mode

Step 14: Continuous Deployment

Our development workflow now becomes:

Developer
    ↓
Git Push
    ↓
GitHub Repository
    ↓
GitHub Actions
    ↓
Validation
    ↓
Streamlit Community Cloud
    ↓
Public Dashboard
Enter fullscreen mode Exit fullscreen mode

GitHub acts as the source of truth for the application.

When we update the project and push the changes to GitHub, our automated GitHub Actions workflow validates the application.

The deployed Streamlit application can then reflect the new version stored in the repository.

This approach gives us a simple CI/CD workflow without needing to manually upload application files every time we make a change.

Conclusion

Building a dashboard is not only about creating charts.

A complete modern data project also involves version control, automation, deployment, and accessibility.

Using Pandas and Plotly, we transformed raw sales information into meaningful visualizations. Streamlit allowed us to transform those visualizations into an interactive web application without developing a traditional frontend.

GitHub provided version control and a public repository, while GitHub Actions added automated validation to the development process.

Finally, Streamlit Community Cloud allowed us to transform a local Python project into a publicly accessible web application.

The complete workflow demonstrates how modern development and data visualization tools can work together:

Data → Analysis → Visualization → Application → Automation → Cloud Deployment

Instead of sharing static screenshots or notebooks, we now have a real interactive dashboard that anyone can access from a browser.

Top comments (0)