DEV Community

IKER ALBERTO SIERRA RUIZ
IKER ALBERTO SIERRA RUIZ

Posted on

Construimos un dashboard interactivo con Streamlit + Plotly, lo automatizamos y lo publicamos en la nube (100% gratis)

🎯 El reto

Como equipo nos propusimos algo simple de enunciar pero completo de ejecutar:
construir un dashboard de visualización de datos, dejar el código en un
repositorio público, automatizar el despliegue, publicarlo en un
cloud/SaaS público y grabar un video de menos de 5 minutos mostrando
todo el proceso.

Elegimos Streamlit + Plotly Express como stack de visualización,
sobre el dataset público Gapminder (esperanza de vida, PBI per cápita y
población por país, continente y año). Este artículo documenta cómo lo
armamos, cómo se despliega solo, y dónde ver el resultado.

🧱 Stack elegido y por qué

  • Streamlit: nos permitió pasar de script de Python a app web interactiva sin escribir HTML/CSS/JS, con recarga automática y componentes nativos (st.metric, st.tabs, st.slider, st.dataframe).
  • Plotly Express: gráficos interactivos (zoom, hover, leyendas clicables) con una sola línea por visualización.
  • Como alternativas dentro del mismo ecosistema evaluamos Bokeh, Seaborn y Shiny for Python; Streamlit ganó por su velocidad de desarrollo y porque Streamlit Community Cloud ofrece despliegue gratuito directamente desde GitHub. ## 📂 1. Repositorio público

Todo el código vive en GitHub, público, con esta estructura:

global-dev-dashboard/
├── app.py
├── requirements.txt
├── Dockerfile
├── tests/test_app.py
├── .github/workflows/ci.yml
├── .github/workflows/docker-publish.yml
├── LICENSE
└── README.md
Enter fullscreen mode Exit fullscreen mode

🔗 Repo: https://github.com/TU-USUARIO/global-dev-dashboard

💻 2. El código del dashboard

El corazón de la app es app.py. Cargamos el dataset, agregamos filtros en
la barra lateral (continente, rango de años) y mostramos KPIs + tres
visualizaciones en pestañas:

import streamlit as st
import plotly.express as px
import pandas as pd

st.set_page_config(page_title="Global Development Dashboard", layout="wide")

@st.cache_data
def load_data() -> pd.DataFrame:
    return px.data.gapminder()

df = load_data()

st.title("🌍 Global Development Dashboard")

continents = st.sidebar.multiselect(
    "Continente", options=sorted(df["continent"].unique()),
    default=sorted(df["continent"].unique()),
)
years = st.sidebar.slider(
    "Rango de años", int(df.year.min()), int(df.year.max()),
    (int(df.year.min()), int(df.year.max())),
)

filtered = df[df.continent.isin(continents) & df.year.between(*years)]

col1, col2, col3 = st.columns(3)
col1.metric("Países", filtered.country.nunique())
col2.metric("Esperanza de vida", f'{filtered.lifeExp.mean():.1f} años')
col3.metric("PBI per cápita", f'${filtered.gdpPercap.mean():,.0f}')

tab1, tab2, tab3 = st.tabs(["📈 Tendencias", "🌐 Dispersión", "📋 Datos"])
with tab1:
    trend = filtered.groupby(["year", "continent"], as_index=False).lifeExp.mean()
    st.plotly_chart(px.line(trend, x="year", y="lifeExp", color="continent"),
                     use_container_width=True)
Enter fullscreen mode Exit fullscreen mode

(código completo en el repo, incluye la pestaña de dispersión con burbujas
por población y la tabla descargable en CSV)
.

requirements.txt se mantiene mínimo a propósito:

streamlit>=1.38
plotly>=5.24
pandas>=2.2
Enter fullscreen mode Exit fullscreen mode

🤖 3. Despliegue automatizado

Automatizamos dos capas:

a) Integración continua (GitHub Actions) — en cada push a main se
ejecuta lint (flake8) y tests (pytest) antes de considerar el cambio
"listo para producción":

name: CI - Lint & Test
on:
  push:
    branches: [main]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with: { python-version: "3.11" }
      - run: pip install -r requirements.txt flake8 pytest
      - run: flake8 app.py --max-line-length=100
      - run: pytest -v
Enter fullscreen mode Exit fullscreen mode

b) Despliegue continuo (Streamlit Community Cloud) — Streamlit Cloud se
conecta directo al repo de GitHub vía webhook: cada push a main que pasa
el CI dispara automáticamente un redeploy de la app, sin pasos manuales ni
credenciales de servidor que gestionar.

Como alternativa multi-cloud, agregamos un segundo workflow
(docker-publish.yml) que construye una imagen Docker y la publica en
GitHub Container Registry en cada push, lista para desplegarse en Render,
Fly.io, Google Cloud Run o Azure Container Apps mediante deploy hooks.

☁️ 4. Publicado en un cloud/SaaS público

La app corre en Streamlit Community Cloud, gratuito y público:

🔗 Demo en vivo: https://TU-APP.streamlit.app

Cualquier persona puede abrir el link, filtrar por continente/año y
descargar los datos filtrados en CSV, sin instalar nada.

🎥 5. Video del proceso (< 5 min)

Grabamos un recorrido corto mostrando: el problema, la app en vivo, el
código clave, el pipeline de GitHub Actions corriendo, y el redeploy
automático en Streamlit Cloud.

📺 Video: https://youtu.be/TU-VIDEO-ID

✅ Resultado y aprendizajes

  • Streamlit + Plotly permiten pasar de datos crudos a dashboard interactivo en minutos.
  • Un pipeline de CI simple (lint + tests) antes del deploy evita romper la demo pública con cada cambio.
  • El despliegue "sin servidores que mantener" (Streamlit Cloud) fue el punto que más tiempo nos ahorró como equipo.
  • Documentar en video obligó a que el proceso fuera realmente reproducible
    de punta a punta, no solo "funciona en mi máquina".

    🔗 Enlaces

  • Repositorio: https://github.com/TU-USUARIO/global-dev-dashboard

  • Demo en vivo: https://TU-APP.streamlit.app

  • Video: https://youtu.be/TU-VIDEO-ID
    ¿Ustedes qué herramienta usarían — Streamlit, Bokeh, Shiny o Dash? Nos
    encantaría leer en los comentarios qué stack eligió cada equipo. 👇

Top comments (0)