πŸš€ Complete Streamlit Learning Guide

Welcome to your comprehensive guide to Streamlit! This repository contains everything you need to master building interactive web applications with Python.

πŸ“‹ Table of Contents

  1. What is Streamlit?

  2. Installation & Setup

  3. Core Concepts

  4. Chapter 1: Basic Elements

  5. Chapter 2: Interactive Widgets

  6. Chapter 3: Layout & UI Components

  7. Chapter 4: Data Handling & Visualization

  8. Chapter 5: External APIs & Live Data

  9. Complete Dashboard Example

  10. Best Practices

  11. Deployment


What is Streamlit?

Streamlit is a powerful, open-source Python library that allows you to create beautiful, interactive web applications with minimal code. It follows a declarative programming paradigm, meaning you describe what you want rather than how to build it.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Streamlit  │───▢│   Python    │───▢│   Declarative   β”‚
β”‚   Library   β”‚    β”‚    Code     β”‚    β”‚   Web Apps      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Key Benefits:

  • No HTML/CSS/JavaScript required

  • Rapid prototyping - Build apps in minutes

  • Automatic UI generation from Python code

  • Real-time updates as you modify code

  • Built-in widgets for common interactions

  • Easy deployment to various platforms


Installation & Setup

Prerequisites

  • Python 3.7 or higher

  • pip package manager

Installation

pip install streamlit

Verify Installation

streamlit hello

Running Your Apps

streamlit run your_app.py

The app will automatically open in your browser at http://localhost:8501


Core Concepts

1. Script Re-execution Model

Every time a user interacts with your app, Streamlit reruns your entire script from top to bottom. This makes the app reactive and ensures the UI always reflects the current state.

2. Session State

Streamlit maintains session state to persist data across reruns:

if 'counter' not in st.session_state:
    st.session_state.counter = 0

3. Caching

Use @st.cache_data to cache expensive computations:

@st.cache_data
def load_data():
    return pd.read_csv('data.csv')

Chapter 1: Basic Elements

The foundation of any Streamlit app starts with basic text and display elements.

File: chapter1.py

import streamlit as st

st.title("Hello, Streamlit!")
st.subheader("This is a simple Streamlit app.")
st.text("Welcome to your first interactive app")
st.write("Choose your favorite variety of coffee")

coffee = st.selectbox("Coffee variety", ["Espresso", "Latte", "Cappuccino", "Americano"])

st.write(f"You chose {coffee}. Excellent choice!")

st.success("App is running successfully!")

Key Components Explained:

Text Elements

  • st.title() - Main heading of your app

  • st.subheader() - Secondary headings

  • st.text() - Plain text display

  • st.write() - Universal display function (auto-detects data type)

Input Widgets

  • st.selectbox() - Dropdown selection menu

    • First parameter: Label text

    • Second parameter: List of options

    • Returns: Selected value

Status Messages

  • st.success() - Green success message

  • st.error() - Red error message

  • st.warning() - Yellow warning message

  • st.info() - Blue info message

Running Chapter 1:

streamlit run chapter1.py

Chapter 2: Interactive Widgets

Streamlit provides a rich set of input widgets for user interaction.

File: chapter2.py

import streamlit as st

st.title("Coffee Maker App")

# Button widget
if st.button("Make Coffee"):
    st.write("Brewing your coffee...")
    st.balloons()  # Fun animation!
    st.success("Your coffee is ready! Enjoy!")

# Checkbox widget
add_sugar = st.checkbox("Add sugar", value=True)
if add_sugar:
    st.write("Sugar added to your coffee!")

# Radio button widget
tea_type = st.radio("Choose your tea type", ["Black", "Green", "Herbal"])
st.write(f"You chose {tea_type} tea. Enjoy your drink!")

# Selectbox widget
flavour = st.selectbox("Choose a flavour", ["Vanilla", "Chocolate", "Caramel"])
st.write(f"You chose {flavour} flavour. Enjoy your drink!")

# Slider widget
sugar = st.slider("Sugar level", 0, 10, 5)
st.write(f"You selected {sugar} teaspoons of sugar.")

# Number input
cups = st.number_input("Enter the number of cups", min_value=1, max_value=10, value=1)

# Text input
name = st.text_input("Enter your name", placeholder="Your name here")
if name:
    st.write(f"Hello, {name}! Welcome to the Coffee Maker App!")

# Date input
dob = st.date_input("Select your date of birth")
if dob:
    st.write(f"Your date of birth is {dob}. Thank you for sharing!")

Widget Categories:

Action Widgets

  • st.button() - Clickable button that returns True when pressed

  • st.download_button() - Button to download files

Selection Widgets

  • st.selectbox() - Single selection dropdown

  • st.multiselect() - Multiple selection dropdown

  • st.radio() - Single selection radio buttons

  • st.checkbox() - Boolean toggle

Input Widgets

  • st.text_input() - Single line text input

  • st.text_area() - Multi-line text input

  • st.number_input() - Numeric input with validation

  • st.slider() - Range selector

  • st.date_input() - Date picker

  • st.time_input() - Time picker

Advanced Parameters:

# Slider with custom range and step
temperature = st.slider(
    "Temperature (Β°C)",
    min_value=0,
    max_value=100,
    value=25,
    step=5,
    help="Adjust the brewing temperature"
)

# Text input with validation
email = st.text_input(
    "Email Address",
    placeholder="user@example.com",
    max_chars=50
)

Chapter 3: Layout & UI Components

Create sophisticated layouts with columns, sidebars, and expandable sections.

File: chapter3.py

import streamlit as st

st.title("Coffee Taste Poll")

# Columns layout
col1, col2 = st.columns(2)

with col1:
    st.header("Masala Coffee")
    vote1 = st.button("Vote for Masala Coffee")

with col2:
    st.header("Adrak Coffee")
    st.image("https://images.unsplash.com/photo-1603052875880-2f8b1c4d3a5e", 
             use_column_width=True)
    vote2 = st.button("Vote for Adrak Coffee")

# Conditional display
if vote1:
    st.success("Thank you for voting for Masala Coffee!")
elif vote2:
    st.success("Thank you for voting for Adrak Coffee!")

# Sidebar components
name = st.sidebar.text_input("Enter your name", placeholder="Your name here")
tea = st.sidebar.selectbox("Choose your tea type", ["Black", "Green", "Herbal"])

st.write(f"Hello, {name}! You chose {tea} tea. Enjoy your drink!")

# Expandable section
with st.expander("Show Coffee Making Instructions"):
    st.write("""
    1. Boil water in a kettle.
    2. Add coffee grounds to a filter.
    3. Pour hot water over the coffee grounds.
    4. Let it brew for a few minutes.
    5. Pour the brewed coffee into a cup.
    6. Add sugar or milk as desired.
    7. Stir well and enjoy your coffee!
    """)

# Markdown formatting
st.markdown('### Welcome to Coffee App')
st.markdown('> Blockquote: Enjoy your coffee with a smile!')

Layout Components:

Column Layout

# Equal width columns
col1, col2, col3 = st.columns(3)

# Custom width ratios
col1, col2 = st.columns([2, 1])  # col1 is 2x wider than col2

# Using columns
with col1:
    st.write("Content in column 1")

with col2:
    st.write("Content in column 2")

Sidebar

# Add widgets to sidebar
st.sidebar.title("Navigation")
page = st.sidebar.selectbox("Choose page", ["Home", "About", "Contact"])

# Sidebar with sections
with st.sidebar:
    st.header("Filters")
    category = st.selectbox("Category", ["All", "Coffee", "Tea"])
    price_range = st.slider("Price Range", 0, 100, (20, 80))

Expandable Sections

# Basic expander
with st.expander("Click to expand"):
    st.write("Hidden content here")

# Expanded by default
with st.expander("Advanced Settings", expanded=True):
    debug_mode = st.checkbox("Debug Mode")
    log_level = st.selectbox("Log Level", ["INFO", "DEBUG", "ERROR"])

Container and Tabs

# Container for grouping elements
with st.container():
    st.write("This is inside a container")
    st.button("Container Button")

# Tabs for organizing content
tab1, tab2, tab3 = st.tabs(["Data", "Charts", "Settings"])

with tab1:
    st.write("Data content")

with tab2:
    st.write("Charts content")

with tab3:
    st.write("Settings content")

Chapter 4: Data Handling & Visualization

Work with files, dataframes, and create interactive visualizations.

File: chapter4.py

import streamlit as st
import pandas as pd

st.title("Coffee Sales Dashboard")

# File upload
uploaded_file = st.file_uploader("Upload your sales data (CSV)", type=["csv"])

if uploaded_file is not None:
    # Read and display data
    data = pd.read_csv(uploaded_file)
    st.write("Data Preview:")
    st.dataframe(data.head())

    # Metrics
    st.subheader("Sales Summary")
    total_sales = data['Sales'].sum()
    st.metric("Total Sales", f"${total_sales:,.2f}")

    # Bar chart
    st.subheader("Sales by Coffee Type")
    sales_by_type = data.groupby('Coffee Type')['Sales'].sum().reset_index()
    st.bar_chart(sales_by_type.set_index('Coffee Type'))

    # Line chart
    st.subheader("Sales Over Time")
    data['Date'] = pd.to_datetime(data['Date'])
    sales_over_time = data.groupby('Date')['Sales'].sum().reset_index()
    st.line_chart(sales_over_time.set_index('Date'))

# Data filtering example
if uploaded_file:
    cities = data["City"].unique()
    selected_city = st.selectbox("Filter by cities", cities)
    filtered_data = data[data["City"] == selected_city]
    st.dataframe(filtered_data)

    # Summary statistics
    st.subheader("Summary Stats")
    st.write(data.describe())

Data Components:

File Upload

# Single file upload
uploaded_file = st.file_uploader(
    "Choose a file",
    type=['csv', 'xlsx', 'json'],
    help="Upload your data file here"
)

# Multiple file upload
uploaded_files = st.file_uploader(
    "Choose files",
    type=['csv'],
    accept_multiple_files=True
)

Data Display

# Display dataframe
st.dataframe(df)  # Interactive table

# Static table
st.table(df.head())  # Static, non-interactive

# Customized dataframe
st.dataframe(
    df,
    use_container_width=True,
    hide_index=True,
    column_config={
        "Price": st.column_config.NumberColumn(
            "Price ($)",
            help="Product price in USD",
            min_value=0,
            max_value=1000,
            format="$%.2f"
        )
    }
)

Metrics & KPIs

# Simple metric
st.metric("Total Sales", "$12,345")

# Metric with delta (change indicator)
st.metric(
    label="Revenue",
    value="$15,000",
    delta="$2,000",
    delta_color="normal"  # "normal", "inverse", or "off"
)

# Multiple metrics in columns
col1, col2, col3 = st.columns(3)
col1.metric("Sales", "1000", "50")
col2.metric("Profit", "$5000", "-200")
col3.metric("Orders", "150", "25")

Built-in Charts

# Line chart
st.line_chart(data)

# Bar chart
st.bar_chart(data)

# Area chart
st.area_chart(data)

# Scatter plot (requires specific format)
chart_data = pd.DataFrame({
    'x': [1, 2, 3, 4],
    'y': [10, 11, 12, 13]
})
st.scatter_chart(chart_data, x='x', y='y')

# Map (requires lat/lon columns)
map_data = pd.DataFrame({
    'lat': [37.76, 37.77, 37.78],
    'lon': [-122.4, -122.41, -122.42]
})
st.map(map_data)

Chapter 5: External APIs & Live Data

Integrate with external services and handle real-time data.

File: chapter5.py

import streamlit as st
import requests

st.title("Live Currency Converter")

# Input widgets
amount = st.number_input("Enter the amount in INR", min_value=1)
target_currency = st.selectbox("Convert to:", ["USD", "EUR", "GBP", "JPY"])

if st.button("Convert"):
    # API call
    url = "https://api.exchangerate-api.com/v4/latest/INR"

    try:
        response = requests.get(url)

        if response.status_code == 200:
            data = response.json()
            rate = data["rates"][target_currency]
            converted = rate * amount
            st.success(f"{amount} INR = {converted:.2f} {target_currency}")
        else:
            st.error("Failed to fetch conversion rate")

    except requests.exceptions.RequestException as e:
        st.error(f"Network error: {e}")
    except KeyError:
        st.error("Currency not found in response")
    except Exception as e:
        st.error(f"An error occurred: {e}")

API Integration Patterns:

Basic API Call with Error Handling

import requests
import streamlit as st

@st.cache_data(ttl=300)  # Cache for 5 minutes
def fetch_weather_data(city):
    api_key = st.secrets["weather_api_key"]  # Store in secrets
    url = f"https://api.openweathermap.org/data/2.5/weather"
    params = {
        "q": city,
        "appid": api_key,
        "units": "metric"
    }

    try:
        response = requests.get(url, params=params, timeout=10)
        response.raise_for_status()
        return response.json()
    except requests.exceptions.RequestException as e:
        st.error(f"Error fetching weather data: {e}")
        return None

# Usage
city = st.text_input("Enter city name")
if city:
    weather_data = fetch_weather_data(city)
    if weather_data:
        st.write(f"Temperature: {weather_data['main']['temp']}Β°C")

Real-time Data Updates

import time
import streamlit as st

# Auto-refresh placeholder
placeholder = st.empty()

# Real-time updates
for i in range(100):
    # Fetch new data
    current_time = time.strftime("%Y-%m-%d %H:%M:%S")

    with placeholder.container():
        st.metric("Current Time", current_time)
        st.metric("Counter", i)

    time.sleep(1)

Complete Dashboard Example

File: demo-dashboard.py

This demonstrates a complete, production-ready dashboard with all the concepts we've learned:

import streamlit as st
import pandas as pd
import numpy as np

# Page configuration
st.set_page_config(
    page_title="Sales Dashboard",
    page_icon="πŸ“ˆ",
    layout="wide",
    initial_sidebar_state="expanded"
)

# Data loading with caching
@st.cache_data
def load_data():
    np.random.seed(42)
    data = {
        "Date": pd.date_range("2024-01-01", periods=60),
        "Region": ["North", "South", "East", "West"] * 15,
        "Product": ["Chai", "Coffee", "Green Tea"] * 20,
        "Revenue": np.random.randint(500, 3000, 60),
        "Units_Sold": np.random.randint(20, 100, 60)
    }
    return pd.DataFrame(data)

df = load_data()

# Sidebar filters
st.sidebar.header("πŸ“Š Dashboard Controls")
region_filter = st.sidebar.multiselect(
    "Select Region(s)",
    options=df["Region"].unique(),
    default=df["Region"].unique()
)

product_filter = st.sidebar.multiselect(
    "Select Product(s)",
    options=df["Product"].unique(),
    default=df["Product"].unique()
)

# Apply filters
filtered_df = df[
    df["Region"].isin(region_filter) & 
    df["Product"].isin(product_filter)
]

# Main dashboard
st.title("πŸ“ˆ Sales Performance Dashboard")

# KPI Section
total_revenue = filtered_df["Revenue"].sum()
total_units = filtered_df["Units_Sold"].sum()
avg_units = filtered_df["Units_Sold"].mean()

col1, col2, col3 = st.columns(3)
col1.metric("πŸ’° Total Revenue", f"β‚Ή{total_revenue:,}")
col2.metric("πŸ“¦ Total Units Sold", f"{total_units:,}")
col3.metric("πŸ“Š Avg Units/Day", f"{avg_units:.1f}")

st.markdown("---")

# Charts section
col1, col2 = st.columns(2)

with col1:
    st.subheader("πŸ“Š Revenue by Product")
    revenue_by_product = filtered_df.groupby("Product")["Revenue"].sum()
    st.bar_chart(revenue_by_product)

with col2:
    st.subheader("πŸ“ˆ Units Sold Over Time")
    units_over_time = filtered_df.groupby("Date")["Units_Sold"].sum()
    st.line_chart(units_over_time)

# Data table
st.subheader("πŸ“‹ Detailed Data")
st.dataframe(
    filtered_df.sort_values("Date", ascending=False),
    use_container_width=True,
    hide_index=True
)

Dashboard Features:

Page Configuration

st.set_page_config(
    page_title="My App",           # Browser tab title
    page_icon="πŸš€",                # Browser tab icon
    layout="wide",                 # "centered" or "wide"
    initial_sidebar_state="expanded"  # "auto", "expanded", "collapsed"
)

Advanced Layouts

# Multiple column layouts
col1, col2, col3, col4 = st.columns([2, 1, 1, 1])

# Nested containers
with st.container():
    st.subheader("Section 1")
    sub_col1, sub_col2 = st.columns(2)
    with sub_col1:
        st.write("Nested content")

Best Practices

1. Performance Optimization

Use Caching

@st.cache_data
def expensive_computation(param):
    # Heavy computation here
    return result

@st.cache_resource
def init_model():
    # Load ML model (singleton pattern)
    return model

Optimize Data Loading

# Load data once and filter in memory
@st.cache_data
def load_full_dataset():
    return pd.read_csv("large_file.csv")

# Filter the cached data
df = load_full_dataset()
filtered_df = df[df['category'] == selected_category]

2. State Management

Session State for Complex Apps

# Initialize session state
if 'step' not in st.session_state:
    st.session_state.step = 1

# Multi-step form
if st.session_state.step == 1:
    name = st.text_input("Name")
    if st.button("Next"):
        st.session_state.name = name
        st.session_state.step = 2
        st.rerun()

elif st.session_state.step == 2:
    st.write(f"Hello, {st.session_state.name}!")
    email = st.text_input("Email")
    if st.button("Submit"):
        # Process form
        st.success("Form submitted!")

3. Error Handling

try:
    # Risky operation
    result = process_data(uploaded_file)
    st.success("Data processed successfully!")

except FileNotFoundError:
    st.error("File not found. Please check the file path.")
except pd.errors.EmptyDataError:
    st.error("The uploaded file is empty.")
except Exception as e:
    st.error(f"An unexpected error occurred: {str(e)}")
    st.info("Please try again or contact support.")

4. User Experience

Loading States

with st.spinner("Processing your request..."):
    time.sleep(3)  # Your actual processing
    st.success("Complete!")

# Progress bar
progress_bar = st.progress(0)
for i in range(100):
    progress_bar.progress(i + 1)
    time.sleep(0.01)

Help and Documentation

st.text_input(
    "API Key",
    type="password",
    help="Enter your API key. You can find this in your account settings."
)

with st.expander("ℹ️ How to use this dashboard"):
    st.write("""
    1. Upload your CSV file using the file uploader
    2. Select filters from the sidebar
    3. View the automatically generated charts
    4. Download results using the download button
    """)

5. Configuration Management

Using Secrets

Create .streamlit/secrets.toml:

[database]
host = "localhost"
port = 5432
username = "admin"
password = "secret123"

[api_keys]
weather_api = "your-api-key-here"

Access in code:

db_config = st.secrets["database"]
api_key = st.secrets["api_keys"]["weather_api"]

Deployment

  1. Push your code to GitHub

  2. Visit share.streamlit.io

  3. Connect your GitHub repository

  4. Your app will be live at https://yourapp.streamlit.app

2. Local Development

# Install requirements
pip install -r requirements.txt

# Run the app
streamlit run app.py

# Run on specific port
streamlit run app.py --server.port 8080

3. Docker Deployment

Create Dockerfile:

FROM python:3.9-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .

EXPOSE 8501

CMD ["streamlit", "run", "app.py", "--server.address", "0.0.0.0"]

4. Requirements File

Create requirements.txt:

streamlit>=1.28.0
pandas>=1.5.0
numpy>=1.21.0
requests>=2.28.0
plotly>=5.15.0

🎯 Next Steps

  1. Explore the code files in this repository:

    • Start with chapter1.py for basics

    • Progress through each chapter

    • Study demo-dashboard.py for a complete example

  2. Try modifications:

    • Change colors and styling

    • Add new widgets

    • Connect to different APIs

    • Create your own datasets

  3. Build your own app:

    • Start with a simple idea

    • Use the patterns from this guide

    • Deploy and share with others

  4. Advanced topics to explore:

    • Custom components

    • Streamlit themes

    • Database connections

    • Authentication

    • Multi-page apps


πŸ”— Additional Resources


πŸ“ Sample Data

The repository includes coffee_sales.csv with sample data you can use to practice:

Date,City,Chai_Type,Cups_Sold,Revenue
2024-01-01,Delhi,Masala,120,1800
2024-01-01,Mumbai,Adrak,100,1500
...

Happy coding with Streamlit! πŸš€

0
Subscribe to my newsletter

Read articles from Arshnoor Singh Sohi directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Arshnoor Singh Sohi
Arshnoor Singh Sohi

πŸ‘¨β€πŸ’» Master's student in Applied Computing (AI Specialization) at University of Windsor πŸ† 1st Place Winner - NLP & Large Language Models Workshop 2025 πŸ”§ I build end-to-end solutions - from distributed file systems in C to production-ready RAG systems achieving 91% precision. Currently exploring the intersection of AI and software engineering. πŸ“Š My projects span the full spectrum: real-time collaborative web apps, intelligent recommendation systems, and machine learning pipelines that actually work in production. 🌱 Always learning, always building. When I'm not debugging code, you'll find me experimenting with the latest AI frameworks or contributing to open source. 🎯 Currently seeking co-op opportunities to apply my skills in real-world challenges. πŸ“ Windsor, ON | πŸ”— Open to connect and collaborate!