Streamlit Overview
Streamlit is a Python framework for rapidly building and deploying interactive web applications for data science and machine learning. Create beautiful web apps with just Python - no frontend development experience required. Apps automatically update in real-time as code changes.
When to Use This Skill
Activate when the user:
Wants to build a web app, dashboard, or data visualization tool Mentions Streamlit explicitly Needs to create an ML/AI demo or prototype Wants to visualize data interactively Asks for a data exploration tool Needs interactive widgets (sliders, buttons, file uploads) Wants to share analysis results with stakeholders Installation and Setup
Check if Streamlit is installed:
python3 -c "import streamlit; print(streamlit.version)"
If not installed:
pip3 install streamlit
Create and run your first app:
Create app.py with Streamlit code
streamlit run app.py
The app opens automatically in your browser at http://localhost:8501
Basic App Structure
Every Streamlit app follows this simple pattern:
import streamlit as st
Set page configuration (must be first Streamlit command)
st.set_page_config( page_title="My App", page_icon="📊", layout="wide" )
Title and description
st.title("My Data App") st.write("Welcome to my interactive dashboard!")
Your app code here
Streamlit automatically reruns from top to bottom when widgets change
Core Capabilities 1. Displaying Text and Data import streamlit as st, pandas as pd
Text elements
st.title("Main Title") st.header("Section Header") st.subheader("Subsection Header") st.text("Fixed-width text") st.markdown("Bold and italic text") st.caption("Small caption text")
Code blocks
st.code(""" def hello(): print("Hello, World!") """, language="python")
Display data
df = pd.DataFrame({ 'Column A': [1, 2, 3], 'Column B': [4, 5, 6] })
st.dataframe(df) # Interactive table st.table(df) # Static table st.json({'key': 'value'}) # JSON data
Metrics
st.metric( label="Revenue", value="$1,234", delta="12%" )
- Interactive Widgets import streamlit as st
Text input
name = st.text_input("Enter your name") email = st.text_input("Email", type="default") password = st.text_input("Password", type="password") text = st.text_area("Long text", height=100)
Numbers
age = st.number_input("Age", min_value=0, max_value=120, value=25) slider_val = st.slider("Select a value", 0, 100, 50) range_val = st.slider("Select range", 0, 100, (25, 75))
Selections
option = st.selectbox("Choose one", ["Option 1", "Option 2", "Option 3"]) options = st.multiselect("Choose multiple", ["A", "B", "C", "D"]) radio = st.radio("Pick one", ["Yes", "No", "Maybe"])
Checkboxes
agree = st.checkbox("I agree to terms") show_data = st.checkbox("Show raw data")
Buttons
if st.button("Click me"): st.write("Button clicked!")
Date and time
date = st.date_input("Select date") time = st.time_input("Select time")
File upload
uploaded_file = st.file_uploader("Choose a file", type=['csv', 'xlsx', 'txt']) if uploaded_file is not None: df = pd.read_csv(uploaded_file) st.dataframe(df)
Download button
st.download_button( label="Download data", data=df.to_csv(index=False), file_name="data.csv", mime="text/csv" )
- Charts and Visualizations import streamlit as st import pandas as pd, numpy as np, matplotlib.pyplot as plt import plotly.express as px
Sample data
df = pd.DataFrame({ 'x': range(10), 'y': np.random.randn(10) })
Streamlit native charts
st.line_chart(df) st.area_chart(df) st.bar_chart(df)
Scatter plot with map data
map_data = pd.DataFrame( np.random.randn(100, 2) / [50, 50] + [37.76, -122.4], columns=['lat', 'lon'] ) st.map(map_data)
Matplotlib
fig, ax = plt.subplots() ax.plot(df['x'], df['y']) ax.set_title("Matplotlib Chart") st.pyplot(fig)
Plotly (interactive)
fig = px.scatter(df, x='x', y='y', title="Interactive Plotly Chart") st.plotly_chart(fig, use_container_width=True)
Altair, Bokeh, and other libraries also supported
- Layout and Containers import streamlit as st
Columns
col1, col2, col3 = st.columns(3) with col1: st.header("Column 1") st.write("Content here") with col2: st.header("Column 2") st.write("More content") with col3: st.header("Column 3") st.write("Even more")
Tabs
tab1, tab2, tab3 = st.tabs(["Overview", "Data", "Settings"]) with tab1: st.write("Overview content") with tab2: st.write("Data content") with tab3: st.write("Settings content")
Expander (collapsible section)
with st.expander("Click to expand"): st.write("Hidden content that can be expanded")
Container
with st.container(): st.write("This is inside a container") st.write("Another line")
Sidebar
st.sidebar.title("Sidebar") st.sidebar.selectbox("Choose option", ["A", "B", "C"]) st.sidebar.slider("Sidebar slider", 0, 100)
- Status and Progress import streamlit as st, time
Success, info, warning, error messages
st.success("Success! Everything worked.") st.info("This is an informational message.") st.warning("This is a warning.") st.error("This is an error message.")
Progress bar
progress_bar = st.progress(0) for i in range(100): time.sleep(0.01) progress_bar.progress(i + 1)
Spinner (loading indicator)
with st.spinner("Processing..."): time.sleep(3) st.success("Done!")
Balloons (celebration)
st.balloons()
Snow (celebration)
st.snow()
- Caching for Performance import streamlit as st, pandas as pd, time
Cache data loading (persists across reruns)
@st.cache_data def load_data(): time.sleep(2) # Simulate slow data load return pd.read_csv('large_file.csv')
Cache resource (connections, models)
@st.cache_resource def load_model(): # Load ML model (expensive operation) return load_my_model()
Use cached data
df = load_data() # Only loads once, then cached model = load_model() # Cached globally
st.write(f"Loaded {len(df)} rows")
- Session State (Persistent Data) import streamlit as st
Initialize session state
if 'count' not in st.session_state: st.session_state.count = 0
Increment counter
if st.button("Increment"): st.session_state.count += 1
st.write(f"Count: {st.session_state.count}")
Store user data across reruns
if 'user_data' not in st.session_state: st.session_state.user_data = {}
name = st.text_input("Name") if name: st.session_state.user_data['name'] = name st.write(f"Hello, {st.session_state.user_data['name']}!")
Common Patterns Pattern 1: Data Dashboard import streamlit as st, pandas as pd, plotly.express as px
st.set_page_config(page_title="Sales Dashboard", layout="wide")
Sidebar filters
st.sidebar.header("Filters") date_range = st.sidebar.date_input("Date Range", []) category = st.sidebar.multiselect("Category", ["A", "B", "C"])
Load data
@st.cache_data def load_sales_data(): return pd.read_csv('sales_data.csv')
df = load_sales_data()
Apply filters
if date_range: df = df[df['date'].between(date_range[0], date_range[1])] if category: df = df[df['category'].isin(category)]
Metrics row
col1, col2, col3, col4 = st.columns(4) col1.metric("Total Revenue", f"${df['revenue'].sum():,.0f}") col2.metric("Orders", f"{len(df):,}") col3.metric("Avg Order", f"${df['revenue'].mean():.2f}") col4.metric("Top Product", df['product'].mode()[0])
Charts
col1, col2 = st.columns(2) with col1: st.subheader("Revenue by Category") fig = px.bar(df.groupby('category')['revenue'].sum().reset_index(), x='category', y='revenue') st.plotly_chart(fig, use_container_width=True)
with col2: st.subheader("Revenue Trend") fig = px.line(df.groupby('date')['revenue'].sum().reset_index(), x='date', y='revenue') st.plotly_chart(fig, use_container_width=True)
Data table
with st.expander("View Raw Data"): st.dataframe(df)
Pattern 2: Data Explorer import streamlit as st, pandas as pd, plotly.express as px
st.title("📊 Data Explorer")
File upload
uploaded_file = st.file_uploader("Upload CSV", type=['csv'])
if uploaded_file: df = pd.read_csv(uploaded_file)
# Show basic info
st.subheader("Dataset Overview")
col1, col2, col3 = st.columns(3)
col1.metric("Rows", len(df))
col2.metric("Columns", len(df.columns))
col3.metric("Memory", f"{df.memory_usage(deep=True).sum() / 1024**2:.2f} MB")
# Column selection
st.subheader("Explore Data")
columns = st.multiselect("Select columns", df.columns.tolist(), default=df.columns.tolist()[:5])
if columns:
st.dataframe(df[columns])
# Statistics
st.subheader("Statistics")
st.write(df[columns].describe())
# Visualization
st.subheader("Visualize")
col1, col2 = st.columns(2)
with col1:
x_col = st.selectbox("X-axis", columns)
with col2:
y_col = st.selectbox("Y-axis", columns)
chart_type = st.radio("Chart Type", ["Scatter", "Line", "Bar"])
if chart_type == "Scatter":
fig = px.scatter(df, x=x_col, y=y_col)
elif chart_type == "Line":
fig = px.line(df, x=x_col, y=y_col)
else:
fig = px.bar(df, x=x_col, y=y_col)
st.plotly_chart(fig, use_container_width=True)
Pattern 3: Multi-Page App
Create a multi-page app with file structure:
app/ ├── main.py └── pages/ ├── 1_📊Dashboard.py ├── 2📈Analytics.py └── 3⚙️_Settings.py
Main page (main.py):
import streamlit as st st.set_page_config(page_title="Multi-Page App", page_icon="🏠")
st.title("Welcome to My App") st.sidebar.success("Select a page above.")
st.markdown(""" This is the home page. Navigate using the sidebar. """)
Pages automatically appear in the sidebar. Each page is a separate Python file.
Form Handling import streamlit as st
Forms prevent rerun on every widget change
with st.form("my_form"): st.write("Fill out the form")
name = st.text_input("Name")
age = st.number_input("Age", min_value=0, max_value=120)
favorite_color = st.selectbox("Favorite Color", ["Red", "Green", "Blue"])
# Form submit button
submitted = st.form_submit_button("Submit")
if submitted:
st.write(f"Name: {name}")
st.write(f"Age: {age}")
st.write(f"Color: {favorite_color}")
Best Practices Use caching - Cache expensive operations with @st.cache_data and @st.cache_resource Session state for persistence - Use st.session_state to persist data across reruns Organize with containers - Use columns, tabs, and expanders for clean layouts Forms for multiple inputs - Prevent reruns with forms when collecting multiple inputs Wide layout for dashboards - Use st.set_page_config(layout="wide") for dashboards Sidebar for controls - Put filters and settings in the sidebar Progress indicators - Show spinners for long operations Common Issues Issue: App reruns on every interaction
Use st.form() to batch inputs or st.session_state to control behavior.
Issue: Slow performance
Cache expensive operations:
@st.cache_data def expensive_computation(param): # Your code here return result
Issue: State not persisting
Use session state:
if 'my_var' not in st.session_state: st.session_state.my_var = initial_value
Resources references/api_reference.md: Quick reference for common Streamlit components Official docs: https://docs.streamlit.io/ API reference: https://docs.streamlit.io/develop/api-reference Gallery: https://streamlit.io/gallery Community: https://discuss.streamlit.io/