Consulta el estado de las playas de Cantabria en tiempo real. Esta aplicación proporciona predicción a 3 días con detalle por mañana y tarde, mareas, índice UV, avisos meteorológicos y estado de la bandera de la Cruz Roja.
Available languages: Español | English
Puedes probar la aplicación aquí: https://playas-cantabria-front.web.app/
Backend API: https://playas-cantabria.onrender.com
- Listado de playas con búsqueda por nombre o municipio y ordenación A-Z / Z-A.
- Detalle de la playa con información completa:
- Predicción a 3 días con selector de día (Hoy, Mañana, Pasado mañana) y fecha.
- Detalle mañana/tarde: cielo, viento y oleaje para cada franja del día.
- Temperatura máxima, del agua y sensación térmica.
- Índice UV con código de colores por nivel.
- Avisos meteorológicos con nivel de severidad.
- Mareas: horas de pleamar y bajamar, con indicador en tiempo real de si la marea sube o baja.
- Cruz Roja: estado de la bandera, cobertura y horario de vigilancia.
- Botón "Cómo llegar" que abre Google Maps con direcciones hasta la playa.
- Mapa interactivo (Leaflet/OpenStreetMap) con tu ubicación actual y acceso directo al detalle de cada playa.
- Modo offline parcial: si el backend no responde en 2.5s, el listado se sirve desde un JSON local y se actualiza cuando el servidor contesta.
La app agrega información de múltiples fuentes con cadena de fallback:
- AEMET (scraping XML/HTML): Predicción enriquecida a 3 días, mareas, avisos y UV real (fuente principal).
- AEMET OpenData API: Predicción a 2 días como respaldo.
- OpenWeatherMap: Datos meteorológicos, UV estimado y predicción de mañana como último recurso.
- Cruz Roja: Estado de la bandera y servicios de socorrismo (scraping).
Caché en memoria con TTL configurable (300s por defecto) y deduplicación singleflight.
El backend sigue una Arquitectura Hexagonal (Puertos y Adaptadores). Las dependencias siempre apuntan hacia adentro: infrastructure → application → domain.
-
Domain(Núcleo)- Entidades:
Beach,Weather,Flag,Tides,BeachForecast. - Puertos (interfaces):
BeachRepository,WeatherProvider,FlagProvider,TidesProvider. - Casos de uso:
GetAllBeaches,GetBeachById,GetBeachDetails. - Sin dependencias de otras capas.
- Entidades:
-
Application(Orquestación)- DTOs:
BeachDTO,BeachDetailsDTO. - Mappers:
BeachMapper,LegacyDetailsMapper. - Servicios:
LegacyDetailsAssembler(orquesta la cadena de fallback). - Validación: Esquemas Zod para parámetros de ruta.
- DTOs:
-
Infrastructure(Exterior)- Express: Servidor, rutas, middlewares.
- Proveedores:
AemetBeachWebScraper,AemetBeachForecastProvider,OpenWeatherWeatherProvider,RedCrossFlagProvider. - Repositorio:
JsonBeachRepository(lee de JSON estático). - Caché:
InMemoryCachecon TTL y singleflight. - DI: Contenedor manual sin framework (
dependencies.ts).
Capa 1: AemetBeachWebScraper → XML/HTML público de aemet.es (3 días, mañana/tarde, mareas, avisos, UV)
Capa 2: AemetBeachForecastProvider → OpenData API con API key (2 días)
Capa 3: OpenWeatherWeatherProvider → OpenWeather API (temp, viento, descripción)
Capa 4: GetBeachDetails → AEMET observación ↔ OpenWeather (hedged, el primero que responde gana)
- Lenguaje: TypeScript v5.5
- Entorno de Ejecución: Node.js v20+
- Framework: Express.js v4.19
- Arquitectura: Hexagonal (Puertos y Adaptadores) con DI manual.
- Validación: Zod
- HTTP: Axios v1.7
- Scraping: Cheerio v1.0
- Codificación: iconv-lite (AEMET sirve ISO-8859-15)
- Gestión de Entorno: Dotenv
- Logging: Winston
- Despliegue: Render (principal), Firebase Functions (alternativo)
- Framework: React 18
- UI Framework: Ionic React
- Lenguaje: TypeScript
- Enrutador: React Router
- Mapas: Leaflet / react-leaflet con OpenStreetMap
- Plataforma Móvil: Capacitor
- Despliegue Web: Firebase Hosting
playas-cantabria/
├── backend/
│ └── src/
│ ├── domain/ # Entidades, puertos, casos de uso
│ ├── application/ # DTOs, mappers, servicios, validación
│ └── infrastructure/ # Express, proveedores, caché, DI, repositorios
├── frontend/
│ └── src/
│ ├── pages/ # Home, PlayaDetalle, MapaPage
│ ├── services/ # Cliente API
│ ├── config/ # Configuración URL API
│ ├── data/ # JSON fallback de playas
│ └── theme/ # Variables CSS
- Node.js v20+
- npm (u otro gestor de paquetes)
git clone https://github.com/oscaruiz/playas-cantabria.git
cd playas-cantabria
# Backend
cd backend
npm install
cp .env.tmp .env
# Rellena .env con tus API keys
# Frontend
cd ../frontend
npm installNecesitas dos terminales:
# Terminal 1 — Backend (http://localhost:4000)
cd backend
npm run dev
# Terminal 2 — Frontend (http://localhost:8100)
cd frontend
npm start| Método | Ruta | Descripción |
|---|---|---|
| GET | /api/beaches |
Listado de todas las playas |
| GET | /api/beaches/:id |
Información básica de una playa |
| GET | /api/beaches/:id/details |
Detalle completo: predicción 3 días, mareas, Cruz Roja, coordenadas |
# Listado
curl "http://localhost:4000/api/beaches"
# Detalle completo (La Concha de Suances)
curl "http://localhost:4000/api/beaches/3908503/details"El endpoint /details consolida datos de AEMET, OpenWeatherMap y Cruz Roja e incluye predicción a 3 días con mañana/tarde, mareas (pleamar/bajamar), índice UV, avisos meteorológicos y coordenadas GPS.
| Variable | Descripción | Default |
|---|---|---|
PORT |
Puerto del servidor | 4000 |
AEMET_API_KEY |
Clave API de AEMET OpenData | — |
OPENWEATHER_API_KEY |
Clave API de OpenWeatherMap | — |
CORS_ORIGIN |
Origen CORS permitido | * |
CACHE_TTL_SECONDS |
TTL de la caché en segundos | 300 |
DEBUG_WEATHER |
Habilita logs detallados y endpoint debug | — |
| Variable | Descripción | Default |
|---|---|---|
REACT_APP_API_BASE_URL |
URL del backend | https://playas-cantabria.onrender.com |
Las contribuciones son bienvenidas. Si tienes ideas, sugerencias o quieres reportar un error, abre un issue en este repositorio.
Este proyecto está bajo la licencia MIT No Commercial (MIT + NC). Consulta el archivo LICENSE para más detalles.
Este proyecto sigue Semantic Versioning. Actualmente en v2.0.0.
-
Incorporar datos de mareas - Añadir más playas
- Mejorar la arquitectura del frontend (estado, tipos discriminados, caching)
- Publicar OpenAPI/Swagger de la API
- Tests E2E básicos (Playwright) para flujos principales


