st.navigation, st.Page y st.switch_page para aplicaciones multipágina

Intermedio
Streamlit
Streamlit
Actualizado: 26/04/2026

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 - Autor del tutorial

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.