Standardizes the structure and navigation of multi-page Streamlit apps using `app_pages/` and shared session state.
Install
mkdir -p .claude/skills/building-streamlit-multipage-apps && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/15353" && unzip -o skill.zip -d .claude/skills/building-streamlit-multipage-apps && rm skill.zipInstalls to .claude/skills/building-streamlit-multipage-apps
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Building multi-page Streamlit apps. Use when creating apps with multiple pages, setting up navigation, or managing state across pages.Key capabilities
- →Structure multi-page Streamlit applications
- →Set up navigation for multiple pages
- →Manage global session state across pages
- →Implement page-specific state
- →Share UI elements across all pages
- →Enable programmatic navigation between pages
How it works
This skill provides a blueprint for structuring Streamlit applications with multiple pages, defining navigation, and managing global and page-specific state.
Inputs & outputs
When to use building-streamlit-multipage-apps
- →Structuring a multi-page app
- →Managing state in streamlit
- →Creating a navigation menu
About this skill
Streamlit multi-page apps
Structure and navigation for apps with multiple pages.
Directory structure
streamlit_app.py # Main entry point
app_pages/
home.py
analytics.py
settings.py
Important: Name your pages directory app_pages/ (not pages/). Using pages/ conflicts with Streamlit's old auto-discovery API and can cause unexpected behavior.
Main module
# streamlit_app.py
import streamlit as st
# Initialize global state (shared across pages)
if "api_client" not in st.session_state:
st.session_state.api_client = init_api_client()
# Define navigation
page = st.navigation([
st.Page("app_pages/home.py", title="Home", icon=":material/home:"),
st.Page("app_pages/analytics.py", title="Analytics", icon=":material/bar_chart:"),
st.Page("app_pages/settings.py", title="Settings", icon=":material/settings:"),
])
# App-level UI runs before page content
# Useful for shared elements like titles
st.title(f"{page.icon} {page.title}")
page.run()
Note: When you handle titles in streamlit_app.py, individual pages should NOT use st.title again.
Navigation position
Few pages (3-7) → Top navigation:
page = st.navigation([...], position="top")
Creates a clean horizontal menu. Great for simple apps. Sections are supported too—they appear as dropdowns in the top nav.
Many pages or nested sections → Sidebar:
page = st.navigation({
"Main": [
st.Page("app_pages/home.py", title="Home"),
st.Page("app_pages/analytics.py", title="Analytics"),
],
"Admin": [
st.Page("app_pages/settings.py", title="Settings"),
st.Page("app_pages/users.py", title="Users"),
],
}, position="sidebar")
Mixed: Some pages ungrouped:
Use an empty string key "" for pages that shouldn't be in a section. These ungrouped pages always appear first, before any named groups. Put all ungrouped pages in a single "" key:
page = st.navigation({
"": [
st.Page("app_pages/home.py", title="Home"),
st.Page("app_pages/about.py", title="About"),
],
"Analytics": [
st.Page("app_pages/dashboard.py", title="Dashboard"),
st.Page("app_pages/reports.py", title="Reports"),
],
}, position="top")
Page modules
# app_pages/analytics.py
import streamlit as st
# Access global state
api = st.session_state.api_client
user = st.session_state.user
# Page-specific content (title is handled in streamlit_app.py)
data = api.fetch_analytics(user.id)
st.line_chart(data)
Global state
Initialize state in the main module only if it's needed across multiple pages:
# streamlit_app.py
st.session_state.api = init_client()
st.session_state.user = get_user()
st.session_state.settings = load_settings()
Tip: Use st.session_state.setdefault("key", default_value) to initialize values only if they don't exist.
Why main module (for global state):
- Runs before every page
- Ensures state is initialized
- Single source of truth
Page-specific state
Use prefixed keys for page-specific state:
# app_pages/analytics.py
if "analytics_date_range" not in st.session_state:
st.session_state.analytics_date_range = default_range()
Share elements between pages
Put shared UI in the entrypoint (before page.run()) so it appears on all pages:
# streamlit_app.py
import streamlit as st
pages = [...]
page = st.navigation(pages)
# Shared title
st.title(f"{page.icon} {page.title}")
# Shared sidebar widgets
with st.sidebar:
st.selectbox("Theme", ["Light", "Dark"])
page.run()
Programmatic navigation
Navigate to another page programmatically:
if st.button("Go to Settings"):
st.switch_page("app_pages/settings.py")
Create navigation links with st.page_link:
st.page_link("app_pages/home.py", label="Home", icon=":material/home:")
st.page_link("https://example.com", label="External", icon=":material/open_in_new:")
Note: Prefer
st.navigationoverst.page_linkfor standard navigation. Do not usest.page_linkto recreate the nav bar you get withst.navigation. Only usest.page_linkwhen linking to pages from somewhere other than the sidebar, or when building a more complex navigation menu.
Conditional pages
Show different pages based on user role, authentication, or any other condition by building the pages list dynamically:
# streamlit_app.py
import streamlit as st
pages = [st.Page("app_pages/home.py", title="Home", icon=":material/home:")]
if st.user.is_logged_in:
pages.append(st.Page("app_pages/dashboard.py", title="Dashboard", icon=":material/bar_chart:"))
if st.session_state.get("is_admin"):
pages.append(st.Page("app_pages/admin.py", title="Admin", icon=":material/settings:"))
page = st.navigation(pages)
page.run()
Common conditions for showing/hiding pages:
st.user.is_logged_infor authenticated usersst.session_stateflags (roles, permissions, feature flags)- Environment variables or secrets
- Time-based access (e.g., beta features)
Imports from pages
When importing from page files in app_pages/, always import from the root directory perspective:
# app_pages/dashboard.py - GOOD
from utils.data import load_sales_data
# app_pages/dashboard.py - BAD (don't use relative imports)
from ..utils.data import load_sales_data
References
When not to use it
- →When building a single-page Streamlit application
- →When using Streamlit's old auto-discovery API for pages
- →When the goal is to recreate the navigation bar with st.page_link
Limitations
- →The page directory must be named app_pages/
- →Global state should be initialized in the main module
- →Page-specific state should use prefixed keys
How it compares
This skill offers a specific, recommended directory structure and navigation setup for Streamlit multi-page apps, avoiding common conflicts and state issues, unlike ad-hoc page creation.
Compared to similar skills
building-streamlit-multipage-apps side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| building-streamlit-multipage-apps (this skill) | 0 | 4mo | No flags | Beginner |
| streamlit | 86 | 9mo | No flags | Intermediate |
| dashboard-build | 6 | 2mo | Review | Advanced |
| developing-with-streamlit | 0 | 4mo | No flags | Beginner |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
streamlit
sverzijl
When working with Streamlit web apps, data dashboards, ML/AI app UIs, interactive Python visualizations, or building data science applications with Python
dashboard-build
mckinsey
A skill that should be invoked whenever a user wants to build a Dashboard or simple app. This skill is Phase 2 of an e2e process that covers the actual build and testing. For Phase 1 (requirements, layout design, visualization selection), use the dashboard-design skill.
developing-with-streamlit
seanyofthedead
Build production-grade Streamlit apps. Used when creating, editing, debugging, or deploying Streamlit applications. Routes to specialized sub-skills for performance, layouts, design, data display, and more.
anywidget-marimo
diegosouzapw
Toolkit for generating custom widgets from scratch for Marimo.
building-data-apps
ironkid90
|
dashboard-view-builder
gitwalter
Building and managing premium statistical dashboards, RAG explorer UIs, warehouse log monitors, and real-time visualization centers.