"Interactive web apps for data science: Streamlit, Panel, and Gradio. Use for prototyping ML models, creating data exploration dashboards, and sharing insights with non-technical stakeholders."
Resources
1Install
npx skillscat add legout/data-agent-skills/data-science-interactive-apps Install via the SkillsCat registry.
SKILL.md
Interactive Web Apps
Use this skill for building lightweight web interfaces to ML models, data visualizations, and analytical tools.
When to use this skill
- ML model demos — let stakeholders interact with predictions
- Data exploration tools — filter, visualize, drill down
- Internal dashboards — monitoring, reporting, self-service analytics
- Prototyping — validate UX before full engineering investment
- A/B test interfaces — experiment with different presentations
Tool selection guide
| Tool | Best For | Strengths |
|---|---|---|
| Streamlit | Rapid ML demos, data apps | Simplest API, large community, great for Python devs |
| Panel | Complex dashboards, reactive layouts | Jupyter integration, flexible layout, HoloViz ecosystem |
| Gradio | ML model sharing, Hugging Face | Built-in sharing, model introspection, API generation |
| Dash (Plotly) | Production dashboards | Fine-grained control, React backend |
| NiceGUI | Desktop + web apps | Native-like UI, async support |
Quick start: Streamlit
# app.py
import streamlit as st
import pandas as pd
import plotly.express as px
st.title("Sales Dashboard")
# Sidebar controls
region = st.sidebar.selectbox("Region", ["All", "North", "South", "East", "West"])
# Load and filter data
df = pd.read_parquet("sales.parquet")
if region != "All":
df = df[df['region'] == region]
# Display metrics
col1, col2, col3 = st.columns(3)
col1.metric("Total Sales", f"${df['sales'].sum():,.0f}")
col2.metric("Orders", len(df))
col3.metric("Avg Order", f"${df['sales'].mean():.2f}")
# Visualization
fig = px.line(df.groupby('date')['sales'].sum().reset_index(), x='date', y='sales')
st.plotly_chart(fig, use_container_width=True)
# Data table
st.dataframe(df.head(100))Run: streamlit run app.py
Quick start: Gradio
import gradio as gr
from transformers import pipeline
# Load model (example: sentiment analysis)
classifier = pipeline("sentiment-analysis")
def predict(text):
result = classifier(text)[0]
return result['label'], result['score']
interface = gr.Interface(
fn=predict,
inputs=gr.Textbox(lines=2, placeholder="Enter text..."),
outputs=[gr.Label(label="Sentiment"), gr.Number(label="Confidence")],
title="Sentiment Analysis",
description="Enter text to analyze sentiment"
)
interface.launch()Quick start: Panel
import panel as pn
import hvplot.pandas
import pandas as pd
pn.extension()
df = pd.read_parquet("data.parquet")
# Widgets
region = pn.widgets.Select(name='Region', options=['All'] + df['region'].unique().tolist())
metric = pn.widgets.RadioBoxGroup(name='Metric', options=['sales', 'profit', 'units'])
# Reactive function
@pn.depends(region, metric)
def plot(region, metric):
data = df if region == 'All' else df[df['region'] == region]
return data.hvplot.line(x='date', y=metric, title=f'{metric.title()} by Date')
# Layout
app = pn.Column(
"# Sales Dashboard",
pn.Row(region, metric),
plot
)
app.servable()Run: panel serve app.py
Core design principles
1) Start simple, iterate
- MVP with one widget + one visualization
- Add complexity only when needed
- Test with real users early
2) Optimize for the audience
| Audience | Approach |
|---|---|
| Executives | Key metrics, simple filters, clean layout |
| Data scientists | Raw data access, parameter tuning, debug info |
| Operations | Refresh buttons, alerts, mobile-friendly |
3) Handle state carefully
# Streamlit: use session_state for persistence
if 'counter' not in st.session_state:
st.session_state.counter = 0
st.session_state.counter += 14) Never expose secrets
# ✅ Use st.secrets (Streamlit Cloud) or environment variables
api_key = st.secrets["openai_api_key"]
# ❌ Never hardcode
api_key = "sk-..."Deployment options
| Platform | Best For | Notes |
|---|---|---|
| Streamlit Community Cloud | Free sharing | GitHub integration, public by default |
| Hugging Face Spaces | ML demos | Free tier, Gradio/Streamlit/Docker |
| Panel + Cloud Run/Heroku | Custom hosting | More control, requires setup |
| Docker + any cloud | Enterprise | Scalable, private, more work |
Common anti-patterns
- ❌ Loading data on every interaction (use caching)
- ❌ Blocking the UI with long computations
- ❌ No error handling for edge cases
- ❌ Hardcoded file paths or credentials
- ❌ Too many widgets (cognitive overload)
- ❌ No mobile consideration
Progressive disclosure
references/streamlit-advanced.md— Caching, custom components, multipage appsreferences/panel-holoviz.md— Linked brushing, geographic visualizationsreferences/gradio-ml.md— Model sharing, API generation, Spaces deploymentreferences/app-testing.md— Automated testing for interactive appsreferences/production-deployment.md— Docker, authentication, scaling
Related skills
@data-science-notebooks— Prototype in notebooks, convert to apps@data-science-model-evaluation— Present model metrics in apps@data-engineering-orchestration— Connect apps to production pipelines