Building Client Prototypes Fast: Streamlit Dashboards in an Afternoon

Part 3 of the Python for FDE track. Last updated: October 2026.

The FDE superpower is turning a Python script into something a client stakeholder can click — same afternoon. Streamlit (pip install streamlit, run with streamlit run app.py) does exactly that: no frontend code, no build step, just Python that renders as a web app. This post builds a client-ready dashboard pattern: widgets, caching, layout, state, and secrets.

Your first dashboard: file upload to insight

The classic FDE demo opener — let the stakeholder drop in their file and see it work on their data:

# app.py — run with: streamlit run app.py
import streamlit as st
import pandas as pd

st.title("Acme — Weekly Client Review")

uploaded = st.file_uploader("Drop the client CSV here", type="csv")
if uploaded:
    df = pd.read_csv(uploaded)
    st.metric("Rows", f"{len(df):,}")
    st.dataframe(df.head(20))
else:
    st.info("Upload a file to begin the demo.")

Widgets: the stakeholder control panel

Filters belong in the sidebar so the main area stays clean. Every widget reruns the script top-to-bottom when changed — that rerun model is the whole mental model of Streamlit:

import streamlit as st

client = st.sidebar.selectbox("Client", ["Acme", "Globex", "Initech"])
min_value = st.sidebar.slider("Minimum order value", 0, 1000, 100)
regions = st.sidebar.multiselect("Regions", ["NA", "EU", "APAC"], default=["NA"])
show_raw = st.sidebar.checkbox("Show raw data", value=False)

st.write(f"Showing **{client}**: orders over ${min_value} in {', '.join(regions)}")
if show_raw:
    st.dataframe(filtered_df)   # defined from your data step above

Caching: don't reload the world on every click

Because the script reruns on every widget change, expensive work needs st.cache_data. It caches by argument values and an optional TTL — the difference between a snappy demo and an awkward silence:

import streamlit as st
import pandas as pd

@st.cache_data(ttl=3600)          # cache for one hour; keyed on `path`
def load_client_data(path: str) -> pd.DataFrame:
    df = pd.read_csv(path, parse_dates=["order_date"])
    return df.dropna(subset=["order_id"])

df = load_client_data("data/orders.csv")
st.metric("Orders loaded", f"{len(df):,}")
# Orders loaded: 1,231

Layout: tabs and columns

Stakeholders scan, they don't scroll. Put the headline numbers in columns and the details in tabs:

import streamlit as st

tab1, tab2 = st.tabs(["Overview", "Drill-down"])

with tab1:
    c1, c2, c3 = st.columns(3)
    c1.metric("Revenue", "$48.2k", "+6%")
    c2.metric("Orders", "1,240", "+38")
    c3.metric("Churn risk", "3", "-1")

with tab2:
    st.bar_chart({"Week 1": [120, 95, 140], "Week 2": [150, 110, 125]})

State: multi-step flows

Some demos need steps — connect, then clean, then show. st.session_state survives reruns, so it holds your wizard's position:

import streamlit as st

if "step" not in st.session_state:
    st.session_state.step = 0

if st.button("Next step"):
    st.session_state.step += 1

steps = ["Connect", "Clean", "Demo"]
st.progress((st.session_state.step + 1) / len(steps))
st.subheader(steps[min(st.session_state.step, len(steps) - 1)])

Secrets: API keys without leaking them

Demos need real API keys, and real API keys must never appear on a shared screen or in a repo. Streamlit's secrets store keeps them out of the code — locally in .streamlit/secrets.toml, in the cloud via the app dashboard:

import streamlit as st
import requests

# .streamlit/secrets.toml (never committed):
# CLIENT_API_KEY = "sk-live-..."
api_key = st.secrets["CLIENT_API_KEY"]

r = requests.get("https://api.client.com/v1/health",
                 headers={"Authorization": f"Bearer {api_key}"}, timeout=10)
st.success("API reachable" if r.ok else f"API returned {r.status_code}")

Key takeaways

  • Streamlit turns a script into a clickable app: pip install streamlit, then streamlit run app.py.
  • The mental model is rerun-on-widget-change — design for it, and put filters in the sidebar.
  • Wrap expensive loads in @st.cache_data so every click doesn't reload the world.
  • Stakeholders scan: columns for headline metrics, tabs for detail.
  • Multi-step demos need st.session_state; secrets need st.secrets, never hardcoded keys.

Next in this series: Data Wrangling for Demos: Turning Messy Client Data into Something Shippable.

Comments

Popular posts from this blog

Java Banking Finance Services and Insurance (BFSI) domain interview questions

JSP Servlet Interview Questions For Freshers Series 1

Java program to check even or odd number