- name
- datahub-espana-architecture
- description
- Arquitectura completa de DataHub España — dashboard de datos en tiempo real con mapa, 35+ pestañas, tabs horizontales superiores, capas de mapa, APIs públicas sin auth, cron-based incremental building
- version
- 3.0.0
- tags
- ["datahub","dashboard","spain","esios","ign","leaflet","chartjs","vanilla-js","open-meteo","ine","air-quality"]
# DataHub España — Arquitectura
## Repo
- **GitHub:** `Ntizar/DataHubEspana` (PÚBLICO)
- **Pages:** `https://ntizar.github.io/DataHubEspana/`
- **Workflow:** `.github/workflows/pages.yml` (actions/deploy-pages@v4)
- **Branch:** `main`
## Estructura
```
DataHubEspana/
├── index.html # Dashboard principal (SPA)
├── data/
│ └── codigos-postales-centroids.json # 251 centroides postales
├── scrapers/ # 19 scrapers Python
│ ├── esios/ # ESIOS/REE — energía
│ ├── aemet/ # AEMET — meteorología
│ ├── boe/ # BOE — boletín oficial
│ ├── borme/ # BORME — mercantil
│ ├── catastro/ # Catastro — catastro
│ ├── contratacion/ # Contratación pública
│ ├── dgt/ # DGT — tráfico
│ ├── embalses/ # Embalses — agua
│ ├── ine/ # INE — demografía
│ ├── ign/ # IGN — geográfico
│ ├── idee/ # IDEE — espacial
│ ├── oapn/ # OAPN — parques nacionales
│ ├── puertos/ # Puertos del Estado
│ ├── subvenciones/ # Subvenciones
│ ├── madrid/ # Madrid CKAN
│ ├── ckan_multi_portal/ # CKAN multi-portal
│ ├── nap_transporte/ # NAP Transportes
│ ├── datos_gob/ # datos.gob.es
│ └── orchestrator_v2/ # Orquestador maestro
└── tools/
├── dashboard-economico/ # Dashboard económico
├── mapa-trafico/ # Mapa de tráfico
└── monitor-energia/ # Monitor de energía
```
## Stack
- **CSS:** Inline CSS (sin framework externo). Diseño limpio profesional.
- **Mapa:** Leaflet 1.9.4 + Layer Control (carreteras, ferrocarriles, choropleth toggleable, parques markers)
- **Charts:** Chart.js 4.4.4
- **Base:** HTML/CSS/JS puro (sin framework)
- **Deploy:** GitHub Pages via GitHub Actions
## Layout v2.6 (2026-06-30) — Tabs horizontales + capas toggleables
- **Pestañas en barra horizontal** `#tab-navbar` arriba del mapa (scrollable horizontal) — **David: "las pestañas deberían salir arriba y se viesen más datos"**
- **Sidebar solo muestra contenido** de la pestaña activa (no botones de tabs)
- **Botón ☰** para colapsar/expandir sidebar
- **Pronóstico 7 días fusionado en Clima** (ya no pestaña separada)
- **Transporte ELIMINADO** (API DGT rota, datos estáticos inútiles — David: "no aporta información")
- **Tipografía reducida:** KPIs 14-17px, títulos 12px, body 10-11px
- **Total: 35+ pestañas** (Panel, Energía, Clima, Agua, Economía, Ambiente, Catastro, Población, Economía Det., Calidad Aire, Demografía, Puertos, Polen, Inundaciones, Suelo + 20 de cron: GBFS, Nieve, Mar, UV, Visibilidad, Ráfagas, Lluvia, Nubosidad, Presión, Fuego, ET0, CAPE, Horas Sol, Rocío, Temp Suelo, Radiación, Sensación, Aire Ext, Mareas, Eólica)
## Capas de datos (13+ pestañas)
### Cron Job Orchestration (20+ tabs)
Cuando se necesitan crear many tabs independientes, usar cron jobs one-shot espaciados 10 min:
- Cada cron: `git pull` → modificar index.html → verificar DOM → commit → push
- **IMPORTANTE:** cada cron debe hacer `git pull` ANTES de modificar para evitar conflictos
- Verificación pre-commit OBLIGATORIA: DOM balance debe ser -1
- Patrón de fix crons: después de crear tabs básicas, segunda tanda que añade selectores, alertas, corrige datos absurdos
### Open-Meteo API — Parámetros current vs daily
`sunrise` y `sunset` **NO** son válidos en `current=`. Solo en `daily=`. Falla silenciosa.
- `snow_depth` viene en **METROS** (×100 para cm)
- Parámetros current válidos: temperature_2m, relative_humidity_2m, apparent_temperature, precipitation, rain, snowfall, snow_depth, weather_code, cloud_cover, pressure_msl, surface_pressure, wind_speed_10m, wind_direction_10m, wind_gusts_10m
### 1. 📊 Panel (vista general)
- KPIs: Población total, Provincias, PVPC, Demanda, Renovables, Temperatura Madrid
- KPIs nuevos v2.3: **AQI Europeo**, **Índice UV** (Open-Meteo Air Quality)
- Último terremoto (USGS)
- Hidroelectricidad (embalses)
### 2. ⚡ Energía (ESIOS/REE)
- **PVPC:** Precio medio spot (€/MWh) — indicator 1001
- **Demanda:** Demanda eléctrica total (MW) — indicator 1293
- **Renovables:** % generación renovable — indicator 1294 (⚠️ fallback 45.2% si 403)
- **CO₂:** Intensidad de emisiones (g/kWh)
- **Gráficos:** PVPC últimas 24h (line), Generación por fuente (doughnut)
### 3. 🌤️ Clima (Open-Meteo) — v2.5: incluye Pronóstico 7 días
- Temperatura, viento, humedad, condición meteorológica
- **Pronóstico 7 días integrado** (cards por día + 3 gráficos: temp, precipitación, viento)
- Click provincia → clima de su capital + pronóstico actualizado
- **Error handling:** showToast + fallback values + setTxt() helper
- API: `https://api.open-meteo.com/v1/forecast`
### 4. 💧 Agua (Embalses)
- Nivel medio por cuenca (%)
- Gráfico de barras por cuenca
- Lista con progress bars por embalse
### 5. 💼 Economía (BOE/BORME)
- Constituciones vs disoluciones (doughnut)
- Datos hardcodeados (mejorable con API real)
### 6. 🌿 Medio Ambiente (OAPN) — v2.6: parques reales con coords
- **16 parques nacionales** con coordenadas reales, superficie (km²), año declaración
- **Click en parque → flyTo en mapa** (zoom 11, 1.5s animación)
- **Markers verdes** toggleables desde layer control del mapa
- **Overlay layer:** `parksOverlay` (L.layerGroup con circle markers verdes)
- Coordenadas: Picos de Europa (43.17,-4.85), Ordesa (42.67,-0.02), Aigüestortes (42.58,1.02), Sierra de Guadarrama (40.85,-3.85), Monfragüe (39.83,-6.05), Cabañeros (39.38,-4.32), Doñana (36.95,-6.35), Sierra Nevada (37.05,-3.37), Tablas de Daimiel (39.15,-3.08), Timanfaya (29.00,-13.83), Caldera de Taburiente (28.75,-17.87), Garajonay (28.10,-17.23), Teide (28.27,-16.64), Archipiélago de Cabrera (39.15,2.95), Islas Atlánticas (42.50,-9.00), Sierra de las Nieves (36.68,-5.02)
### 7. 🏗️ Catastro — v2.6: datos reales por provincia
- **Provincia seleccionada:** nombre, código INE, CCAA, capital
- **Superficie** (km²), **Densidad** (hab/km², calculada), **Municipios** (conteo)
- **Enlace directo** a Sede Electrónica del Catastro para la provincia
- Se actualiza al seleccionar provincia en el mapa
### 9. 👥 Población (INE) — NUEVO v2.1
- Población total: 47.615.034
- Densidad, extranjeros, crecimiento
- **Gráfico:** Top 10 CCAA (barras horizontales)
- **Gráfico:** Distribución por edad (doughnut)
### 10. 📈 Economía detallada — NUEVO v2.1
- PIB: 1.418.352M€, Paro: 11,2%, IPC: 2,8%
- **Gráfico:** PIB por sector (barras horizontales)
- **Gráfico:** Paro por provincias Top 10 (barras coloreadas)
### 11. 🚢 Puertos — v2.6: flyTo en mapa + datos en vivo
- Contenedores TEU, Mercancía total, Pasajeros, Cruceros
- **Gráfico:** Top 10 puertos por tonelaje (barras horizontales, clickable)
- **Lista interactiva:** 10 puertos costeros con click → panel detalle
- **Panel detalle puerto** (al click): oleaje, viento, temperatura, humedad, amanecer/atardecer
- ** flyTo en mapa:** Al hacer click en puerto → `map.flyTo([port.lat, port.lon], 12, {duration: 1.5})`
- **APIs:** Open-Meteo Marine (oleaje) + Open-Meteo Weather (clima)
- **Puertos con coordenadas:** Algeciras, Valencia, Barcelona, Bilbao, Las Palmas, Tenerife, Cartagena, Huelva, A Coruña, Gijón
### 12. 🌬️ Calidad del Aire (Open-Meteo Air Quality) — NUEVO v2.3
- **API:** `https://air-quality-api.open-meteo.com/v1/air-quality` (CAMS European forecasts, sin auth)
- **KPIs en tiempo real:** AQI Europeo, PM2.5, PM10, Ozono O₃, NO₂, CO, Índice UV, Polvo, SO₂
- **Gráficos:**
- Evolución contaminantes 24h (líneas, hourly data)
- Distribución contaminantes (donut)
- **Se actualiza al seleccionar provincia** → fetch con centroides
- **Fórmula:** `?current=european_aqi,us_aqi,pm10,pm2_5,nitrogen_dioxide,ozone,carbon_monoxide,sulphur_dioxide,dust,uv_index&hourly=pm10,pm2_5,nitrogen_dioxide,ozone,carbon_monoxide,sulphur_dioxide&past_days=1&forecast_days=0`
- **Verificado:** Madrid AQI=38, PM2.5=8.8, O3=96, NO2=10.4, CO=126, UV=7.3
### 13. 📊 Demografía (INE) — NUEVO v2.3
- **API:** `https://servicios.ine.es/wstempus/js/ES/DATOS_TABLA/9681?tip=AM&nult=1` (población por CCAA y sexo)
- **KPIs:** Población total, Mujeres, Hombres, Tasa dependencia, Índice envejecimiento
- **Gráficos:**
- Pirámide poblacional (barras horizontales divergentes, mujeres=rosa/hombres=azul)
- Población por CCAA (top 10, barras horizontales)
- Distribución por sexo (pie chart)
- **Verificado:** total=47,615,034, women=24,304,407, men=23,310,627, aging=112.7, dependency=49.2%
- **Tabla INE 2852:** población por provincia y sexo (159 entries, funciona)
### 14. 🌾 Polen (Open-Meteo Air Quality) — NUEVO v2.4
- **API:** `https://air-quality-api.open-meteo.com/v1/air-quality?...¤t=alder_pollen,birch_pollen,grass_pollen,mugwort_pollen,olive_pollen,ragweed_pollen`
- **KPIs:** Gramen, Olivo, Abedul, Aliso, Artemisa, Ambrosía (gr/m³)
- **Gráficos:** Distribución por tipo (barras) + evolución 24h (líneas)
- **Se actualiza al seleccionar provincia**
### 15. 🌊 Inundaciones (Open-Meteo Flood) — v2.6: ríos por provincia
- **API:** `https://flood-api.open-meteo.com/v1/flood?...&daily=river_discharge&past_days=7&forecast_days=7`
- **KPIs:** Caudal actual, Caudal máx 7d, Caudal mín 7d, Caudal medio
- **Nombre del río:** Mapeo de 52 provincias → río principal (Madrid→Tajo, Barcelona→Llobregat, Sevilla→Guadalquivir, Bilbao→Nervión, Valencia→Turia, Zaragoza→Ebro)
- **Gráfico:** Línea de caudal 14 días (7 pasados + 7 previsión) con nombre del río en título
- **Se actualiza al seleccionar provincia** → muestra río correspondiente
### 16. 🌡️ Suelo (Open-Meteo Forecast) — NUEVO v2.4
- **API:** `https://api.open-meteo.com/v1/forecast?...&hourly=soil_temperature_6cm,soil_temperature_18cm,soil_temperature_54cm,soil_moisture_0_to_1cm,soil_moisture_1_to_3cm,soil_moisture_3_to_9cm,soil_moisture_9_to_27cm`
- **KPIs:** Temp suelo 6/18/54cm, Humedad suelo 0-1/3-9/9-27cm
- **Gráficos:** Temperatura por profundidad (3 líneas) + Humedad por profundidad (3 líneas)
## Mapa — Capas interactivas (v2.6)
### Base tiles
- **CARTO light_all** (por defecto): `https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png`
- **OSM estándar**: `https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png`
### Overlay layers (toggleables desde Leaflet layer control)
- **Carreteras** (OpenStreetMap HOT): `https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png`
- **Ferrocarriles** (OpenRailwayMap): `https://tiles.openrailwaymap.org/standard/{z}/{x}/{y}.png`
- **Provincias (coropleta)**: `provincesOverlay` (L.layerGroup) — choropleth de 52 provincias
- **Parques Nacionales**: `parksOverlay` (L.layerGroup) — 16 markers verdes con circle markers
### Layer control
```javascript
const baseMaps = { 'CARTO': baseOSM, 'OSM': baseOSMStd };
const overlayMaps = { 'Carreteras': roadsLayer, 'Ferrocarriles': railwaysLayer, 'Provincias': provincesOverlay, 'Parques': parksOverlay };
L.control.layers(baseMaps, overlayMaps).addTo(map);
```
### Choropleth (toggleable)
- 52 provincias con GeoJSON simplificado (487KB)
- Canvas renderer para rendimiento
- Click provincia → zoom + panel detalle derecho
- **Toggle:** `provincesOverlay` permite activar/desactivar la capa desde el layer control
## Diseño actual (v2.5) — Limpio profesional, compacto
### Estilo de cards (CRÍTICO: sin border-left)
- **NO usar `border-left` de colores** → David rechazó explícitamente ("las cards se notan que son ia")
- **Usar gradientes sutiles** en background: `linear-gradient(135deg, #f0fdf4 0%, #ffffff 100%)` para green
- **Hover elevación**: `box-shadow: 0 4px 12px rgba(0,0,0,0.08); transform: translateY(-1px)`
- **Colores**: Azul #2563eb, Naranja #f97316, Verde #16a34a, Rojo #dc2626
- **Fondo KPIs**: `#f8fafc` base con gradientes por tipo (green/orange/red/blue)
- **Border radius**: 10px para KPIs, 12px para cards
- **Sin glass/blur/saturate** → rechazado en v1
### Paleta
- Background: `#f8fafc`
- Cards: `#ffffff` + `border: 1px solid #e2e8f0`
- Texto primario: `#0f172a`
- Texto secundario: `#64748b`
- Labels KPI: `#94a3b8` (más sutiles)
### Sidebar
- Width: 380px, colapsable con botón ☰
- **NO contiene tabs** (v2.5: tabs en #tab-navbar horizontal arriba)
- Solo muestra contenido de la pestaña activa
### Mapa
- Tile: CARTO light_all
- Choropleth: 52 provincias con GeoJSON simplificado (487KB)
- Canvas renderer para rendimiento
- Click provincia → zoom + panel detalle derecho
## Cron Jobs existentes
- `mastermind-autoconfig` — diario 09:00 UTC
- `chromadb-reindex-semanal` — domingo 04:00 UTC
- **DataHub 20 tabs creation** — 20 crons espaciados 10 min (12:15-15:25 UTC) — crear pestañas nuevas
GitHub에서 보기