Developing, testing, and deploying Streamlit data applications on Snowflake...
Build interactive data applications using Streamlit, test them locally, and deploy to Snowflake's native Streamlit environment.
Execution Modes:
Critical: Support both local development and Snowflake deployment:
import streamlit as st
from snowflake.snowpark.context import get_active_session
from snowflake.snowpark import Session
@st.cache_resource
def get_snowpark_session():
try:
return get_active_session() # Snowflake
except:
return Session.builder.config('connection_name', 'default').create() # Local
For connection setup, see the snowflake-connections skill for:
~/.snowflake/connections.toml# Install dependencies (pin Streamlit version to match Snowflake)
uv pip install --system -r requirements.txt
# Example requirements.txt
streamlit==1.46.0 # Must match Snowflake version
snowflake-snowpark-python
pandas
streamlit run app.py
# Or with environment overrides (see snowflake-connections skill)
SNOWFLAKE_DATABASE=MY_DB streamlit run app.py
pytest streamlit_app/tests/ -v
Use Playwright MCP for interactive testing:
See TESTING_GUIDE.md for patterns.
snow streamlit deploy --replace -c default
Include Streamlit deployment in migration scripts.
See TROUBLESHOOTING.md for common issues.
Complementary Testing:
playwright-mcp skill - Automate browser testing for Streamlit appsUse playwright-mcp for visual testing, form validation, responsive design testing, and accessibility checks of your Streamlit applications.
ā DO: Modular data access
# utils/data_loader.py
class DataQueries:
def __init__(self, session):
self.session = session
def get_sales(self, start_date, end_date):
return self.session.sql(f"""
SELECT * FROM sales
WHERE date BETWEEN '{start_date}' AND '{end_date}'
""").to_pandas()
# app.py
from utils.data_loader import DataQueries
session = get_snowpark_session()
queries = DataQueries(session)
df = queries.get_sales('2024-01-01', '2024-12-31')
st.dataframe(df)
ā DON'T: Mix SQL with UI code
Always cache your session to avoid reconnection overhead:
@st.cache_resource
def get_snowpark_session():
"""Get or create Snowpark session (cached)"""
try:
return get_active_session() # When running in Snowflake
except:
from snowflake.snowpark import Session
return Session.builder.config('connection_name', 'default').create()
ā DO: Group inputs in forms
with st.form("customer_form"):
name = st.text_input("Name")
email = st.text_input("Email")
phone = st.text_input("Phone")
if st.form_submit_button("Save"):
save_customer(name, email, phone)
st.success("Customer saved!")
ā DON'T: Trigger rerun on every input (causes rerun on every keystroke)
Provide helpful feedback:
try:
save_customer(name, email)
st.success("ā
Customer saved successfully!")
except ValueError as e:
st.error(f"ā Invalid input: {e}")
st.info("š” Tip: Check that email format is correct")
except Exception as e:
st.error(f"ā Unexpected error: {e}")
st.info("š” Please contact support if this persists")
ā DO: 2 levels maximum
col1, col2 = st.columns(2)
with col1:
label_col, input_col = st.columns([1, 3])
with label_col:
st.markdown("**Name:**")
with input_col:
name = st.text_input("Name", label_visibility="collapsed")
ā DON'T: 3+ levels of nested columns (causes Streamlit errors)
@st.cache_data(ttl=600) # Cache for 10 minutes
def load_sales_data(start_date, end_date):
return session.sql(f"""
SELECT * FROM sales
WHERE date BETWEEN '{start_date}' AND '{end_date}'
""").to_pandas()
# Initialize state
if 'data' not in st.session_state:
st.session_state.data = load_data()
# Access throughout app
df = st.session_state.data
if st.button("Run Analysis"):
with st.spinner("Analyzing..."):
result = expensive_computation()
st.session_state.result = result
if 'result' in st.session_state:
st.write(st.session_state.result)
Some Streamlit features don't work in Snowflake:
| Feature | Status | Alternative |
|---|---|---|
st.dialog() |
ā Not supported | Use st.expander() or modals |
st.toggle() |
ā Not supported | Use st.checkbox() |
st.rerun() |
ā ļø Older versions only | Use st.experimental_rerun() |
st.connection() |
ā Not supported | Use get_active_session() |
Only Snowflake Anaconda packages available:
# environment.yml
name: streamlit_env
channels:
- snowflake
dependencies:
- pandas
- plotly
# ā DON'T include:
# - streamlit (already provided)
# - snowflake-snowpark-python (already provided)
Check package availability: https://repo.anaconda.com/pkgs/snowflake/
Don't specify Python version - Snowflake controls this:
# ā DON'T DO THIS
dependencies:
- python=3.11 # Wrong!
# ā
DO THIS
dependencies:
- pandas
- plotly
Problem: Two widgets with same implicit key
Solution: Add explicit keys
st.text_input("Name", key="customer_name")
st.text_input("Name", key="product_name")
Check before deploying:
python -c "import ast; ast.parse(open('streamlit_app/app.py').read())"
Ensure proper fallback:
def get_snowpark_session():
try:
return get_active_session() # Snowflake
except:
from snowflake.snowpark import Session
return Session.builder.config('connection_name', 'default').create()
Some parameters not supported in Snowflake:
border=False in st.form()border=True in st.container()hide_index=True in st.dataframe() (older versions)pytest streamlit_app/tests/ -vstreamlit run streamlit_app/app.pyenvironment.yml only has non-default packages# Method 1: Snowflake CLI (Recommended)
snow streamlit deploy --replace --connection default
# Method 2: Schemachange
schemachange deploy --config-folder . --connection-name default
ā DO:
session = get_active_session() # Uses Snowflake auth
ā DON'T:
password = "secret123" # Never do this!
# Check user role
current_role = session.sql("SELECT CURRENT_ROLE()").collect()[0][0]
if current_role == "ADMIN":
st.write("Admin features visible")
else:
st.info("Admin access required")
def save_customer(name, email):
if not name or len(name) < 2:
raise ValueError("Name must be at least 2 characters")
if "@" not in email:
raise ValueError("Invalid email format")
# Proceed with save
...
connections.py - Required session pattern for local/Snowflake compatibilitysnowflake-connections skill - Connection setup, authentication, and multi-environment
configurationplaywright-mcp skill - Browser testing automation for Streamlit appsGoal: Transform AI agents into expert Streamlit developers who build production-ready data applications with proper code organization, performance optimization, and Snowflake-specific best practices.