DEV Community

RODRIGO SIDNEY COLQUE QUISPE
RODRIGO SIDNEY COLQUE QUISPE

Posted on

Building and Deploying an Interactive Analytics Dashboard with Streamlit, GitHub Actions, and Streamlit Community Cloud

How to create an executive business intelligence dashboard in pure Python, automate continuous integration with GitHub Actions, and deploy live to the cloud with zero-downtime automation.


Published on: Medium / Dev.to / Hashnode

Reading Time: 8 min read

Tags: #python #datascience #streamlit #devops #cicd #cloud #plotly

GitHub Repository: https://github.com/Rodrig0496/AG-01-Building-and-Deploying-an-Interactive-Analytics-Dashboard

Live Demo: https://ag-01-analytics-dashboard.streamlit.app


πŸš€ Introduction

In today’s data-driven landscape, static PDF reports and spreadsheet exports are no longer sufficient for business decision-makers. Executives and operational teams expect interactive, real-time, and accessible analytical dashboards that allow them to filter date ranges, explore regional performance, and drill down into granular KPIs on demand.

Historically, developing custom analytical web applications required a full-stack engineering team proficient in JavaScript (React/Vue), backend APIs (FastAPI/Flask), CSS styling, and complex cloud infrastructure.

While tools like Dash (Plotly), R Shiny, Bokeh, and static charting libraries like Seaborn each have their distinct strengths:

  • Seaborn / Matplotlib: Great for exploratory static exploratory charts in Jupyter Notebooks, but lack built-in web reactivity.
  • Bokeh: Powerful for interactive web canvas plots, but requires significant boilerplate for complex app UI states.
  • Dash: Highly customizable and production-grade, but demands deep familiarity with HTML/CSS components and reactive callback decorators.
  • Shiny for Python: Excellent reactive paradigm, but still carries a steeper learning curve for teams coming strictly from Python data analysis.

Enter Streamlit: the open-source Python framework that has revolutionized how data scientists and engineers turn data scripts into shareable web applications in minutes, using 100% pure Python.

In this guide, we walk through the complete end-to-end lifecycle:

  1. Designing a production-grade Executive Sales & KPI Dashboard using Streamlit and Plotly.
  2. Structuring a clean, public open-source repository.
  3. Automating validation and testing through CI/CD pipelines using GitHub Actions.
  4. Deploying to a public Cloud / SaaS platform (Streamlit Community Cloud) with automated continuous deployment.

πŸ“ System Architecture & Workflow

The architecture follows modern DevOps and GitOps practices for data applications:

flowchart LR
    A[Local Development<br>Streamlit + Plotly] -->|git push| B[Public GitHub Repository]
    B -->|Triggers| C[GitHub Actions CI<br>Linting & Smoke Tests]
    B -->|Webhook Sync| D[Streamlit Community Cloud<br>Public SaaS Hosting]
    D --> E[Live Web Dashboard<br>Accessible Worldwide]

Key Workflow Pillars:

  • Developer Experience: Write clean Python code with reactive data caching (@st.cache_data).
  • Quality Assurance: GitHub Actions automatically lints code and runs headless smoke tests on every push.
  • Continuous Deployment (CD): Streamlit Community Cloud watches the main branch and deploys updates instantaneously with zero manual server configuration.

πŸ“ Repository Structure

A clean, reproducible directory structure is vital for both collaboration and automated cloud buildpacks:

AG-01-Building-and-Deploying-an-Interactive-Analytics-Dashboard/
β”œβ”€β”€ .github/
β”‚   └── workflows/
β”‚       └── ci.yml               # Automated CI pipeline (linting & headless tests)
β”œβ”€β”€ .streamlit/
β”‚   └── config.toml              # UI styling theme & production server flags
β”œβ”€β”€ app.py                       # Main Streamlit dashboard application
β”œβ”€β”€ requirements.txt             # Pinned Python package dependencies
β”œβ”€β”€ .gitignore                   # Ignore caches, virtual environments & secrets
└── README.md                    # Project documentation, live links & setup guide
Enter fullscreen mode Exit fullscreen mode

πŸ› οΈ Step 1: Building the Interactive Streamlit Dashboard

Our application, app.py, provides a comprehensive executive analytics experience:

  • KPI Metric Scorecards with comparative deltas.
  • Interactive Time-Series Chart tracking Gross Revenue vs. Net Profit.
  • Market Share Donut Chart highlighting regional distribution.
  • Category Performance Grouped Bar Chart analyzing product lines.
  • Segment Profitability Scatter Plot correlating volume with profit margins.
  • Dynamic Sidebar Filters with multi-selects and date-range pickers.
  • In-Memory CSV Exporter for tabular data inspection.

1.1 Configuring Page Layout & Custom Styling

We initialize a wide layout and apply subtle dark-mode styling adjustments using Streamlit's native st.set_page_config and injected CSS:

import streamlit as st
import pandas as pd
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
from datetime import datetime, timedelta

st.set_page_config(
    page_title="Executive Sales & KPI Dashboard",
    page_icon="πŸ“Š",
    layout="wide",
    initial_sidebar_state="expanded",
)
Enter fullscreen mode Exit fullscreen mode

1.2 Optimized Data Caching with @st.cache_data

One of Streamlit's most powerful features is intelligent caching. By decorating our data ingestion function with @st.cache_data, Streamlit memoizes the dataset in memory, preventing expensive computations from re-running on every filter click:

@st.cache_data(ttl=3600)
def generate_sample_sales_data(num_records: int = 1500) -> pd.DataFrame:
    np.random.seed(42)
    end_date = datetime.now()
    start_date = end_date - timedelta(days=365)

    date_range = [
        start_date + timedelta(days=int(d))
        for d in np.random.uniform(0, 365, num_records)
    ]

    regions = ["North America", "Europe", "Asia-Pacific", "Latin America", "Middle East"]
    categories = {
        "Cloud Solutions": ["Enterprise SaaS", "Data Storage", "Cloud Compute", "Cybersecurity"],
        "Hardware": ["Servers", "Workstations", "Networking Gear", "IoT Hubs"],
        "Professional Services": ["Cloud Migration", "AI Consulting", "Managed Support", "DevOps Audit"]
    }

    # Generate realistic revenue and profit margins
    units_sold = np.random.randint(1, 15, size=num_records)
    base_unit_prices = np.random.uniform(150, 4500, size=num_records)
    gross_sales = np.round(units_sold * base_unit_prices, 2)
    profit = np.round(gross_sales * np.random.uniform(0.15, 0.42, size=num_records), 2)

    data = pd.DataFrame({
        "Order_ID": [f"ORD-{10000 + i}" for i in range(num_records)],
        "Date": pd.to_datetime(date_range),
        "Region": np.random.choice(regions, size=num_records),
        "Customer_Segment": np.random.choice(["Enterprise", "Mid-Market", "SMB", "Government"], size=num_records),
        "Category": np.random.choice(list(categories.keys()), size=num_records),
        "Gross_Sales": gross_sales,
        "Net_Profit": profit,
    })
    data["Month_Year"] = data["Date"].dt.to_period("M").dt.to_timestamp()
    return data.sort_values("Date")

raw_data = generate_sample_sales_data()
Enter fullscreen mode Exit fullscreen mode

1.3 Interactive Sidebar Controls & Filtering

Streamlit's declarative syntax allows us to construct interactive UI controls directly in the sidebar:

with st.sidebar:
    st.markdown("### βš™οΈ Filter Controls")

    # Time Window Filter
    min_date = raw_data["Date"].min().date()
    max_date = raw_data["Date"].max().date()
    date_selection = st.date_input("Select Time Window", value=(min_date, max_date))

    # Geographic Multi-Select
    selected_regions = st.multiselect(
        "Geographic Regions",
        options=sorted(raw_data["Region"].unique()),
        default=sorted(raw_data["Region"].unique())
    )

# Filter logic
filtered_data = raw_data[
    (raw_data["Date"].dt.date >= date_selection[0]) &
    (raw_data["Date"].dt.date <= date_selection[1]) &
    (raw_data["Region"].isin(selected_regions))
]
Enter fullscreen mode Exit fullscreen mode

1.4 High-Impact Visualizations with Plotly

Combining Streamlit with Plotly allows us to generate responsive, hardware-accelerated interactive charts. For example, rendering our monthly revenue trajectory:

monthly_trend = filtered_data.groupby("Month_Year")[["Gross_Sales", "Net_Profit"]].sum().reset_index()

fig_trend = go.Figure()
fig_trend.add_trace(go.Scatter(
    x=monthly_trend["Month_Year"],
    y=monthly_trend["Gross_Sales"],
    name="Gross Sales",
    mode="lines+markers",
    line=dict(color="#6366F1", width=3),
    fill="tozeroy",
    fillcolor="rgba(99, 102, 241, 0.15)"
))
fig_trend.update_layout(template="plotly_dark", hovermode="x unified")
st.plotly_chart(fig_trend, use_container_width=True)
Enter fullscreen mode Exit fullscreen mode

βš™οΈ Step 2: Continuous Integration & Automated Testing

Deploying data applications without automated tests is risky. A broken library version or syntax typo can crash your production dashboard. We implement a continuous integration workflow using GitHub Actions in .github/workflows/ci.yml.

Every time a team member pushes code or opens a Pull Request to main, the workflow executes:

name: Streamlit Dashboard CI/CD Pipeline

on:
  push:
    branches: [ main, master ]
  pull_request:
    branches: [ main, master ]

jobs:
  validate-and-test:
    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.11"
          cache: "pip"

      - name: πŸ“¦ Install Dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
          pip install flake8

      - name: πŸ” Lint Code with Flake8
        run: |
          flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics

      - name: πŸ§ͺ Smoke Test App Compilation
        run: |
          python -c "import app; print('App syntax and imports verified successfully!')"

      - name: πŸš€ Verify Headless Streamlit Startup
        run: |
          timeout 10s streamlit run app.py --server.headless=true --server.port=8501 || [ $? -eq 124 ]
          echo "Streamlit successfully launched in headless mode!"
Enter fullscreen mode Exit fullscreen mode

Why This Automated CI Step Matters:

  • Catches Dependency Conflicts: Guarantees that requirements.txt contains valid, installable packages.
  • Headless Smoke Test: Validates that the Streamlit server boots up and serves traffic without throwing unhandled startup exceptions.
  • Guards Production: Prevents broken code from being pushed to the live cloud platform.

☁️ Step 3: Deploying to a Public Cloud / SaaS Platform

For public deployment, we select Streamlit Community Cloudβ€”a native public cloud SaaS platform providing global hosting, zero-configuration SSL, and native GitOps integration.

Step-by-Step Deployment Walkthrough:

  1. Push your code to GitHub:
   git init
   git add .
   git commit -m "feat: complete executive streamlit dashboard with CI pipeline"
   git branch -M main
   git remote add origin https://github.com/Rodrig0496/AG-01-Building-and-Deploying-an-Interactive-Analytics-Dashboard.git
   git push -u origin main
Enter fullscreen mode Exit fullscreen mode
  1. Connect Streamlit Community Cloud:

  2. Deploy the Application:

    • Click on the "New app" button.
    • Select your repository: Rodrig0496/AG-01-Building-and-Deploying-an-Interactive-Analytics-Dashboard.
    • Set the Branch to: main.
    • Set the Main file path to: app.py.
    • (Optional) Customize your App URL subdomain: https://ag-01-analytics-dashboard.streamlit.app.
    • Click "Deploy!".
  3. Automated Continuous Deployment (CD):
    Streamlit Community Cloud registers a webhook with your GitHub repository. Whenever you or a teammate pushes commits to main:

    • The GitHub Actions CI pipeline runs and validates your code.
    • Streamlit Cloud automatically pulls the new commit, installs updated dependencies, and performs a live rolling reload without downtime.

(Alternative Cloud Providers: You can also deploy this containerized app to **Render, **Hugging Face Spaces, **AWS App Runner, or **Google Cloud Run* using a lightweight Dockerfile).*


πŸ”— Live Application & Public Repository

The source code and live deployed instance are publicly accessible:

Resource Link
πŸ“¦ Public GitHub Repository https://github.com/Rodrig0496/AG-01-Building-and-Deploying-an-Interactive-Analytics-Dashboard
πŸš€ Live Cloud Dashboard https://ag-01-analytics-dashboard.streamlit.app
πŸ“„ Automated CI/CD Workflow .github/workflows/ci.yml

πŸ’‘ Lessons Learned & Best Practices

  1. Always Use Caching: Uncached data loading leads to laggy interactions because Streamlit re-executes scripts top-to-bottom on state changes. Use @st.cache_data for dataframes and @st.cache_resource for database connections or ML models.
  2. Containerize Server Configurations: Use .streamlit/config.toml to lock in headless mode and consistent branding colors so your app looks identical locally and in the cloud.
  3. Automate Smoke Testing: The timeout 10s streamlit run test in GitHub Actions saves hours of debugging by catching missing cloud packages before your users see an error screen.
  4. Design for Responsiveness: Utilize st.columns() and Plotly's use_container_width=True to ensure your dashboard renders gracefully on both ultra-wide desktop monitors and mobile devices.

🎯 Conclusion

Modern data professionals need more than just analytical algorithmsβ€”they need the ability to communicate insights effectively through accessible web applications.

By combining Streamlit for rapid UI development, Plotly for interactive visualization, GitHub Actions for automated CI testing, and Streamlit Community Cloud for automated continuous deployment, you can deliver production-grade data products in hours instead of weeks.


πŸ’¬ Let's Connect!

Have questions or suggestions on dashboard architecture or cloud automation? Feel free to leave a comment below or connect on LinkedIn / GitHub. If you found this article helpful, don't forget to leave a πŸ‘ or star the repository!

Top comments (0)