st-page-state is an architectural framework designed to transform Streamlit into a foundation for enterprise-grade internal systems. It replaces loose, brittle st.session_state dictionaries with typed, declarative classes that ensure your application survives the “refresh test”.
The Problem
Native Streamlit state management relies on magic strings, lacks type safety, and is volatile. If a user refreshes their browser or shares a link, their complex “work-in-progress” context is lost.
The Technical Solution
st-page-state treats state as a first-class citizen through structured schemas and bi-directional URL synchronization.
For Developers (DX):
-
Typed Schemas: Use
StateVarto define state with strict types (int,bool,list[str],datetime.date, etc.) and default values. -
Namespace Isolation: Every class has its own isolated storage bucket, eliminating key collisions in modular, large-scale apps.
-
Lifecycle Hooks: Define
on_initandon_changelogic directly within your state models to manage side effects cleanly. -
Introspection: Use
.dump()to instantly export state for API payloads or logging.
For Users (UX):
-
Indestructible Context: Every interaction is synced to the URL. Progress survives page refreshes and can be shared instantly via deep linking.
-
Intelligent URL Management:
url_selfishautomatically purges stale parameters from other modules, keeping the address bar clean and professional. -
State Defense:
restore_url_on_touchensures that if a user manually deletes a URL parameter, it is instantly repopulated from the session context upon access. -
Cross-Module Synergy:
share_url_withallows independent components—like a global sidebar and a main workspace—to coexist in the URL seamlessly.
Implementation Example
import streamlit as st
from st_page_state import PageState, StateVar
class AppWorkflow(PageState):
class Config:
url_prefix = "app_" # Module isolation
url_selfish = True # Claims URL focus for this component
share_url_with = ["NavState"] # Explicitly coexists with navigation
task_id: str = StateVar(default="", url_key="tid")
priority: int = StateVar(default=1, url_key="pri")
# Programmatically claiming focus cleans the URL and sets the application context
if st.button("Resume Task"):
AppWorkflow.focus()
Stop treating your users’ progress as temporary. Build persistent, modular, and professional systems.
GitHub: [https://github.com/ju-sants/st-page-state]
PyPI: pip install st-page-state