Have you ever stared at a spreadsheet until your eyes crossed?
I certainly have.
We spend hours cleaning data, analyzing trends, and finding that one golden insight.
But then comes the hard part.
We have to present it.
Usually, this means static PowerPoint slides or screenshots of Excel charts.
The excitement dies instantly.
Your audience doesn't want to see a static table.
They want to play with the data.
They want to ask, "What happens if I change this variable?" or "How does this look for region X?"
That is where data storytelling comes in.
And you don't need to be a web developer to build a tool that lets them do that.
Today, Iโm going to show you how to take a simple dataset and turn it into a fully interactive web application.
We are going to use Python and a library that feels like magic: Streamlit.
Why I Swear by Streamlit

I used to dread building dashboards.
In the past, if I wanted to share a model or a visualization, I had to learn Flask or Django.
I had to wrestle with HTML, CSS, and JavaScript.
It was a nightmare for a data scientist who just wanted to code in Python.
Then I found Streamlit.
Streamlit turns data scripts into shareable web apps in minutes.
All in pure Python.
No front-end experience is required.
It creates a bridge between your Jupyter Notebook and a polished product.
It allows you to iterate incredibly fast.
You change a line of Python, hit save, and the web app updates instantly.
For this tutorial, we represent 'My Core Pick', so we are focusing on quality and speed.
Let's dive into how you can build your first narrative dashboard.
Setting The Stage: Your Environment

Before we write a single line of code, we need to set up our workspace.
I assume you have Python installed.
If not, grab the latest version from python.org.
I always recommend working in a virtual environment to keep dependencies clean.
Open your terminal or command prompt.
Create a new folder for your project.
bash
mkdir streamlit_dashboard
cd streamlit_dashboard
Now, create a virtual environment.
bash
python -m venv venv
Activate it (on Windows use venv\Scripts\activate, on Mac/Linux use source venv/bin/activate).
Now, let's install the stars of the show.
We need Streamlit for the app, Pandas for data manipulation, and Plotly for beautiful interactive charts.
bash
pip install streamlit pandas plotly
That is it.
We are ready to code.
The Foundation: Loading Your Data

Create a new file called app.py.
Open it in your favorite code editor (I use VS Code).
Let's start by importing our libraries.
python
import streamlit as st
import pandas as pd
import plotly.express as px
Now, we need a title.
Streamlit makes this incredibly easy.
python
st.set_page_config(page_title="Sales Dashboard", layout="wide")
st.title("๐ Global Sales Narrative")
st.markdown("## Analyze sales performance across different regions.")
Next, we need data.
For this example, let's pretend we have a CSV file named sales_data.csv.
(You can use any dataset you have, or download a sample Superstore Sales dataset online).
We will write a function to load the data.
Why a function?
Because we want to use Streamlitโs caching mechanism.
The Power of Caching
Every time a user interacts with a Streamlit app (clicks a button, changes a filter), the entire script reruns from top to bottom.
If you are loading a 500MB CSV file, that will be painfully slow.
We use the @st.cache_data decorator to fix this.
It tells Streamlit: "If this function has run before, just give me the saved result. Don't run it again."
Here is how I write it:
```python
@st.cache_data
def get_data():
df = pd.read_csv("sales_data.csv")
# A little cleaning helps
df["Order Date"] = pd.to_datetime(df["Order Date"])
return df
df = get_data()
```
Now, letโs verify it worked.
I like to display the raw data initially just to check my sanity.
python
if st.checkbox("Show Raw Data"):
st.dataframe(df.head())
Save your file.
Go to your terminal and run:
bash
streamlit run app.py
A browser window will pop up.
Congratulations, you have a running web app.
Constructing the Narrative: Sidebar and Filters
A story is better when the listener chooses the path.
Static dashboards are boring because they try to show everything to everyone.
We want to give the user control.
Streamlit provides a sidebar specifically for this purpose.
It keeps the main area clean for visualizations.
Let's add a filter for the "Region" and "Year".
Creating the Sidebar
We use st.sidebar to place elements on the left.
```python
st.sidebar.header("Filter Options")
Create a multiselect for Region
region = st.sidebar.multiselect(
"Select Region:",
options=df["Region"].unique(),
default=df["Region"].unique()
)
```
Now, we need to actually filter the dataframe based on this selection.
This is where the interactivity happens.
python
df_selection = df.query("Region == @region")
If the user removes "North America" from the sidebar, df_selection updates instantly.
Let's verify the data is reacting.
We can display some top-level metrics (KPIs) right at the top of the main page.
Displaying KPIs
I love using the st.metric component.
It looks professional and highlights the numbers that matter.
Let's calculate Total Sales and Average Rating based on the filtered data.
```python
total_sales = int(df_selection["Sales"].sum())
average_rating = round(df_selection["Rating"].mean(), 1)
left_column, right_column = st.columns(2)
with left_column:
st.metric(label="Total Sales", value=f"${total_sales:,}")
with right_column:
st.metric(label="Average Rating", value=f"{average_rating} โญ")
```
Notice the st.columns(2)?
This is how we manage layout.
It splits the screen into two equal width columns.
It breaks up the vertical flow and makes the dashboard look designed, not just dumped on the screen.
Visualizing the Story
Now we have data that reacts to user input.
It is time to visualize it.
While Streamlit has basic charts, I prefer Plotly Express.
Plotly charts are interactive by default.
You can hover over data points, zoom in, and download the chart as a PNG.
The Bar Chart
Let's answer the question: "Which product line is performing best?"
We will create a bar chart showing Sales by Product Line.
```python
sales_by_product = (
df_selection.groupby(by=["Product Line"]).sum()[["Sales"]].sort_values(by="Sales")
)
fig_product_sales = px.bar(
sales_by_product,
x="Sales",
y=sales_by_product.index,
orientation="h",
title="Sales by Product Line",
color_discrete_sequence=["#0083B8"] * len(sales_by_product),
template="plotly_white",
)
```
Now we have the figure object (fig_product_sales).
We need to render it in Streamlit.
python
st.plotly_chart(fig_product_sales, use_container_width=True)
The use_container_width=True argument is crucial.
It ensures the chart expands to fill the width of the column or screen.
It makes the app look responsive on different screen sizes.
The Time Series
Every data story needs a timeline.
Let's show how sales have trended over time.
This helps identify seasonality or sudden drops.
```python
Group by month
df_selection["month_year"] = df_selection["Order Date"].dt.to_period("M")
line_chart_data = df_selection.groupby(df_selection["month_year"].astype(str))["Sales"].sum().reset_index()
fig_sales_over_time = px.line(
line_chart_data,
x="month_year",
y="Sales",
title="Sales Over Time",
template="plotly_white"
)
st.plotly_chart(fig_sales_over_time, use_container_width=True)
```
Now, when you change the Region in the sidebar, both the Bar Chart and the Line Chart update immediately.
The user is exploring the story, not just reading it.
Polishing the User Experience
We have the functionality down.
But a professional dashboard needs a little polish.
At 'My Core Pick', we believe the difference between good and great is in the details.
Hiding the Default Style
Streamlit comes with a "hamburger" menu in the top right and a "Made with Streamlit" footer.
For a clean, professional look, I usually hide these using CSS injection.
Yes, I said we don't need CSS, but this is a tiny optional snippet I keep in my back pocket.
python
hide_st_style = """
<style>
#MainMenu {visibility: hidden;}
footer {visibility: hidden;}
header {visibility: hidden;}
</style>
"""
st.markdown(hide_st_style, unsafe_allow_html=True)
Adding Context
Don't just show a chart.
Tell the user what they are looking at.
Use st.markdown to add commentary or explain anomalies in the data.
For example, below the line chart, you could add:
python
st.markdown("---")
st.caption("Note: Sales dipped in Q2 due to supply chain shortages in the North region.")
This context turns raw numbers into actual business intelligence.
Deployment: Sharing Your Story
You built it. It runs locally.
But itโs trapped on your laptop.
To let your team or the world see it, you need to deploy it.
The easiest way, by far, is Streamlit Community Cloud.
Here is the workflow:
-
Create a requirements.txt file. This tells the server which libraries to install.
Run this in your terminal: pip freeze > requirements.txt.
-
Push your code to GitHub. Create a repository and upload your app.py, sales_data.csv, and requirements.txt.
-
Sign up for Streamlit Cloud. Connect it to your GitHub account.
-
Select your repository. Click "Deploy".
In about two minutes, you will have a live URL.
You can email that link to your boss, your client, or post it on LinkedIn.
They can open it on their phone or laptop.
No installation required on their end.
Conclusion
We just went from a static CSV file to a fully interactive, deployed web application.
And we did it with less than 100 lines of Python code.
This is the power of Streamlit.
It democratizes data visualization.
It allows data scientists to become full-stack developers without the steep learning curve.
Your data has a story to tell.
Don't stifle it in a spreadsheet.
Give it a voice.
Build the dashboard, deploy it, and let your users explore the narrative for themselves.
I encourage you to try this weekend.
Grab a dataset you care aboutโmaybe your Spotify listening history or your fitness tracking data.
Build a dashboard for yourself.
Once you start building tools that react to you, you will never want to go back to static slides again.