Estructura de una aplicación multipágina
Desde Streamlit 1.36, la forma recomendada de crear aplicaciones multipágina es usando st.navigation en el archivo principal (app.py) y definiendo cada página con st.Page:
flowchart LR
subgraph Entry["app.py (entrypoint)"]
P1[st.Page inicio.py]
P2[st.Page catálogo.py]
P3[st.Page carrito.py]
P4[st.Page perfil.py]
Nav[st.navigation dict]
P1 --> Nav
P2 --> Nav
P3 --> Nav
P4 --> Nav
Nav --> Run[pg.run]
end
subgraph Sidebar["Sidebar autogenerada"]
Sec1["Sección Tienda"]
Sec2["Sección Cuenta"]
Sec1 --> L1[Inicio]
Sec1 --> L2[Catálogo]
Sec1 --> L3[Carrito]
Sec2 --> L4[Perfil]
end
Run --> Sidebar
L2 -->|st.switch_page| L3
L4 -->|Guard con session_state| L1
mi_app/
├── app.py # Archivo principal con st.navigation
├── pages/
│ ├── inicio.py
│ ├── dashboard.py
│ ├── configuracion.py
│ └── perfil.py
└── .streamlit/
└── config.toml
st.Page: definir una página
st.Page crea un objeto que representa una página de la aplicación:
# app.py
import streamlit as st
inicio = st.Page("pages/inicio.py", title="Inicio", icon="🏠", default=True)
dashboard = st.Page("pages/dashboard.py", title="Dashboard", icon="📊")
configuracion = st.Page("pages/configuracion.py", title="Configuración", icon="⚙️")
perfil = st.Page("pages/perfil.py", title="Mi perfil", icon="👤")
Parámetros de st.Page:
| Parámetro | Descripción |
|-----------|-------------|
| path | Ruta al archivo .py de la página |
| title | Texto que aparece en el menú de navegación |
| icon | Emoji o icono de Material Symbols |
| url_path | URL personalizada (por defecto se deriva del nombre del archivo) |
| default | Si es True, esta página se muestra al arrancar la app |
st.navigation: construir el menú
st.navigation recibe una lista de objetos st.Page o un diccionario con secciones, y construye automáticamente el menú en la barra lateral:
# app.py
import streamlit as st
# Definir páginas
inicio = st.Page("pages/inicio.py", title="Inicio", icon="🏠", default=True)
dashboard = st.Page("pages/dashboard.py", title="Dashboard", icon="📊")
analisis = st.Page("pages/analisis.py", title="Análisis", icon="🔍")
configuracion = st.Page("pages/configuracion.py", title="Configuración", icon="⚙️")
perfil = st.Page("pages/perfil.py", title="Mi perfil", icon="👤")
# Navegación con secciones agrupadas
pg = st.navigation({
"Principal": [inicio, dashboard],
"Herramientas": [analisis],
"Cuenta": [configuracion, perfil]
})
pg.run() # Ejecuta la página activa
Contenido de cada página
Cada archivo de página es un script Python normal con contenido Streamlit:
# pages/dashboard.py
import streamlit as st
import pandas as pd
import numpy as np
st.title("📊 Dashboard de ventas")
st.caption("Datos del último trimestre")
# Generar datos de ejemplo
np.random.seed(42)
df = pd.DataFrame({
"mes": ["Enero", "Febrero", "Marzo"],
"ventas": np.random.randint(50000, 150000, 3),
"gastos": np.random.randint(30000, 80000, 3)
})
col1, col2, col3 = st.columns(3)
col1.metric("Ventas totales", f"€{df['ventas'].sum():,}")
col2.metric("Gastos totales", f"€{df['gastos'].sum():,}")
col3.metric("Beneficio", f"€{(df['ventas'] - df['gastos']).sum():,}")
st.bar_chart(df, x="mes", y=["ventas", "gastos"])
# pages/inicio.py
import streamlit as st
st.title("🏠 Bienvenido")
st.write("Selecciona una sección en el menú lateral para comenzar.")
st.info("Usa el menú de la izquierda para navegar entre páginas.")
st.switch_page: redirigir programáticamente
st.switch_page navega a otra página de forma programática, sin que el usuario tenga que hacer clic en el menú:
# pages/inicio.py
import streamlit as st
st.title("Inicio")
if st.button("Ir al Dashboard"):
st.switch_page("pages/dashboard.py")
if st.button("Configurar mi cuenta"):
st.switch_page("pages/configuracion.py")
Flujo de autenticación con switch_page
Un uso habitual es proteger páginas y redirigir al login si el usuario no está autenticado:
# app.py
import streamlit as st
login_page = st.Page("pages/login.py", title="Iniciar sesión", icon="🔑")
inicio = st.Page("pages/inicio.py", title="Inicio", icon="🏠")
dashboard = st.Page("pages/dashboard.py", title="Dashboard", icon="📊")
perfil = st.Page("pages/perfil.py", title="Perfil", icon="👤")
# Mostrar páginas distintas según si el usuario está autenticado
if st.session_state.get("usuario_autenticado"):
pg = st.navigation([inicio, dashboard, perfil])
else:
pg = st.navigation([login_page])
pg.run()
# pages/login.py
import streamlit as st
st.title("🔑 Iniciar sesión")
with st.form("form_login"):
usuario = st.text_input("Usuario")
contraseña = st.text_input("Contraseña", type="password")
enviado = st.form_submit_button("Entrar", type="primary")
if enviado:
if usuario == "admin" and contraseña == "1234":
st.session_state.usuario_autenticado = True
st.session_state.nombre_usuario = usuario
st.switch_page("pages/inicio.py")
else:
st.error("Credenciales incorrectas.")
# pages/inicio.py
import streamlit as st
# Guard de autenticación
if not st.session_state.get("usuario_autenticado"):
st.switch_page("pages/login.py")
st.title(f"¡Hola, {st.session_state.nombre_usuario}!")
st.success("Has iniciado sesión correctamente.")
if st.button("Cerrar sesión"):
st.session_state.usuario_autenticado = False
st.switch_page("pages/login.py")
Menú dinámico según rol de usuario
# app.py
import streamlit as st
# Páginas comunes
login_page = st.Page("pages/login.py", title="Iniciar sesión", icon="🔑", default=True)
inicio = st.Page("pages/inicio.py", title="Inicio", icon="🏠")
perfil = st.Page("pages/perfil.py", title="Perfil", icon="👤")
# Páginas solo para administradores
admin_usuarios = st.Page("pages/admin_usuarios.py", title="Gestión de usuarios", icon="👥")
admin_config = st.Page("pages/admin_config.py", title="Configuración del sistema", icon="🔧")
if not st.session_state.get("autenticado"):
pg = st.navigation([login_page])
elif st.session_state.get("rol") == "admin":
pg = st.navigation({
"Principal": [inicio, perfil],
"Administración": [admin_usuarios, admin_config]
})
else:
pg = st.navigation({
"Principal": [inicio, perfil]
})
pg.run()
Compatibilidad con la estructura legacy (carpeta pages/)
La estructura anterior de Streamlit (antes de 1.36) usaba una carpeta pages/ sin st.navigation. Sigue funcionando por compatibilidad, pero st.navigation ofrece mayor control sobre el menú y la lógica de autenticación:
# Estructura legacy (sigue funcionando)
app.py
pages/
1_Dashboard.py # El prefijo numérico controla el orden
2_Análisis.py
3_Configuración.py
La convención recomendada para proyectos nuevos es usar st.navigation en app.py.
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Streamlit es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de Streamlit
Explora más contenido relacionado con Streamlit y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
Organizar una aplicación en múltiples páginas con st.navigation y st.Page. Definir páginas con título, icono y ruta de archivo usando st.Page. Agrupar páginas en secciones con secciones del diccionario en st.navigation. Redirigir programáticamente a otra página con st.switch_page. Controlar la visibilidad de páginas según el estado de sesión del usuario.