chore: untrack docs de fase i fitxers raw duplicats (ja ignorats)
This commit is contained in:
@@ -1,29 +0,0 @@
|
||||
# Deploy a Vercel
|
||||
|
||||
## Opción A — Dashboard (recomendada para primer deploy)
|
||||
|
||||
1. Ve a https://vercel.com/new
|
||||
2. Conecta el repo `itziarZG/Vivienda` desde GitHub
|
||||
3. En "Project Name" escribe `casestancades`
|
||||
4. En "Root Directory" selecciona `web`
|
||||
5. Vercel detecta Astro automáticamente y usa Node 22 (definido en `web/vercel.json`)
|
||||
6. Click "Deploy"
|
||||
7. La URL será `https://casestancades.vercel.app`
|
||||
|
||||
## Opción B — CLI
|
||||
|
||||
```bash
|
||||
cd web
|
||||
npx vercel login # abre navegador para autorizar
|
||||
npx vercel link # vincula el proyecto
|
||||
npx vercel --prod # deploy a producción
|
||||
```
|
||||
|
||||
## Variables de entorno
|
||||
|
||||
No requiere ninguna variable. Todo es estático.
|
||||
|
||||
## Dominio propio
|
||||
|
||||
Más adelante (post-MVP): comprar `.cat`/`.org`/`.es` y configurarlo en
|
||||
Vercel → Settings → Domains.
|
||||
-159
@@ -1,159 +0,0 @@
|
||||
# FASE 0 - Setup (semana 1)
|
||||
|
||||
## Objetivo
|
||||
|
||||
Tener el entorno listo y los datos crudos descargados y validados, sin procesar. Al cerrar esta fase, `git status` muestra una estructura limpia y `data/raw/` contiene los datasets originales descargados, cada uno abrible sin errores.
|
||||
|
||||
## Tareas
|
||||
|
||||
### Estructura de carpetas
|
||||
- [x] Crear en `/Users/ichi/Desktop/DEV/VIvienda/`:
|
||||
- `data/raw/` - datos originales, inmutables
|
||||
- `data/processed/` - datasets intermedios
|
||||
- `data/output/` - parquet, tiles, JSONs finales
|
||||
- `web/` - codigo Astro
|
||||
- `docs/` - PDFs, capturas, metodologia extendida
|
||||
- `scripts/` - pipeline Python
|
||||
|
||||
### Repositorio
|
||||
- [x] `git init` en `/Users/ichi/Desktop/DEV/VIvienda/`
|
||||
- [x] Crear `.gitignore` que ignore:
|
||||
- `data/raw/*.xlsx` y `data/raw/*.csv.gz` (datos pesados)
|
||||
- `data/processed/`
|
||||
- `data/output/`
|
||||
- `node_modules/`
|
||||
- `.venv/`, `__pycache__/`
|
||||
- `.env`, `.env.local`
|
||||
- [x] Hacer commit inicial con estructura + `.gitignore` + este PLAN (commit `53f24de`)
|
||||
|
||||
### Reorganizacion de archivos existentes
|
||||
- [x] Mover 15 JPGs unicos a `docs/conferencia-OHIB-2025/` (5 duplicados borrados)
|
||||
- [x] Mover `viviendas vacias-hipotecas.xlsx` y `39365(1).xlsx` a `data/raw/`
|
||||
- [x] Mover `Info.pdf` a `docs/conferencia-OHIB-2025/`
|
||||
- [x] Documentar el origen de cada archivo en `data/raw/ORIGEN.md`
|
||||
|
||||
### Entorno Python
|
||||
- [x] `uv` disponible (v0.7.21)
|
||||
- [x] `uv venv .venv` (Python 3.10.18 seleccionado por uv para compatibilidad con geopandas)
|
||||
- [x] `requirements.txt` con: pandas, openpyxl, geopandas, duckdb, shapely, pyproj, fiona, pyarrow
|
||||
- [x] `uv pip install -r requirements.txt` (todas las deps instaladas)
|
||||
- [x] Verificar: pandas 2.3.3, geopandas 1.1.4, duckdb 1.5.4, shapely 2.1.2, pyproj 3.7.1, fiona 1.10.1, openpyxl 3.1.5, pyarrow 25.0.0
|
||||
|
||||
### Entorno Node
|
||||
- [x] Node 17.1.0 estaba instalado via nvm pero requiere 20+ para Astro
|
||||
- [x] `nvm install 20` (v20.20.2) y `nvm alias default 20`
|
||||
- [x] pnpm v9.15.9 instalado (version 9 porque la 10+ requiere Node 22.13)
|
||||
|
||||
### Descarga de datos externos
|
||||
- [x] Descargar **shapefile de secciones censales de Espana 2025** desde INE
|
||||
- URL final: `https://www.ine.es/prodyser/cartografia/seccionado_2025.zip` (57.5 MB)
|
||||
- Shapefile procesado: filtrado a Illes Balears (674 features, 67 municipios, 1 provincia)
|
||||
- Reproyectado de EPSG:25830 a EPSG:4326 (WGS84)
|
||||
- Guardado como `data/raw/secciones_balears.gpkg` (5.3 MB)
|
||||
- [x] Descargar **Inside Airbnb listings** Mallorca (45.741 listings) y Menorca (8.492 listings)
|
||||
- URL Mallorca: `https://data.insideairbnb.com/spain/islas-baleares/mallorca/2026-06-23/data/listings.csv.gz`
|
||||
- URL Menorca: `https://data.insideairbnb.com/spain/islas-baleares/menorca/2026-06-30/data/listings.csv.gz`
|
||||
- [x] Recibir **HUT Eivissa 2026** del usuario (archivo HTML-as-xls, convertido a `hut_eivissa_2026-07-14.csv` con 2.369 registros y 18.184 plazas)
|
||||
- [x] Recibir **IBESTAT Formentera 2019** del usuario (archivo OLE .xls, convertido a `ibestat_formentera_2019.json` con 1.375 establecimientos y 14.935 plazas)
|
||||
- [x] **Insight del usuario**: el problema real son los ilegales, no los legales. Mallorca/Menorca (Airbnb) capturan realidad; Eivissa/Formentera (HUT) solo capturan legal. **La diferencia entre ambas cifras ES la denuncia narrativa**.
|
||||
|
||||
### Validacion
|
||||
- [x] Shapefile: 36.554 features Espana, 674 en Illes Balears, CRS WGS84 OK
|
||||
- [x] XLSXs validados con openpyxl. Solo sheet `tabla-59531` de `viviendas vacias-hipotecas.xlsx` es el dato util (los otros 5 sheets son hipotecas). `39365(1).xlsx` tiene 1 sheet util (`tabla-39365`).
|
||||
- [x] Listings Airbnb Mallorca y Menorca validados (90 columnas, lat/lon/room_type/price/availability_365 OK)
|
||||
- [x] HUT Eivissa 2026 validado: 2.369 registros en 5 municipios + 5 anomalias. Columna `Referencia cadastral` (20 chars) geocodificable.
|
||||
- [x] IBESTAT Formentera 2019 validado: 1.375 establecimientos, 14.935 plazas. Datos agregados a nivel isla.
|
||||
- [x] Anotado en `data/raw/VALIDACION.md`
|
||||
|
||||
### Cierre
|
||||
- [x] Commit final con tag `fase-0-completa` (commits `1e86070` y `99ad1f8`)
|
||||
- [x] Actualizar PLAN.md: marcar Fase 0 como completada
|
||||
- [x] Anotar problemas y decisiones en este documento
|
||||
|
||||
## Comandos clave
|
||||
|
||||
```bash
|
||||
# Estructura
|
||||
cd /Users/ichi/Desktop/DEV/VIvienda
|
||||
mkdir -p data/raw data/processed data/output web docs/conferencia-OHIB-2025 scripts
|
||||
|
||||
# Git
|
||||
git init
|
||||
git add .
|
||||
git commit -m "chore: estructura inicial del proyecto"
|
||||
|
||||
# Python
|
||||
brew install uv # o pipx install uv
|
||||
uv venv .venv
|
||||
source .venv/bin/activate
|
||||
uv pip install pandas openpyxl geopandas duckdb shapely pyproj fiona pyarrow
|
||||
|
||||
# Node
|
||||
brew install node pnpm # o nvm install 20 && npm i -g pnpm
|
||||
|
||||
# Validacion shapefile (despues de descargar)
|
||||
python -c "import geopandas as gpd; gdf = gpd.read_file('data/raw/secciones_censales_balears.shp'); print(gdf.head()); print('CRS:', gdf.crs); print('Features:', len(gdf))"
|
||||
|
||||
# Validacion listings
|
||||
python -c "import pandas as pd; df = pd.read_csv('data/raw/eivissa_listings.csv.gz', low_memory=False); print(df.shape); print(df.columns.tolist()[:20])"
|
||||
|
||||
# Validacion XLSX
|
||||
python -c "import pandas as pd; df = pd.read_excel('data/raw/viviendas vacias-hipotecas.xlsx', sheet_name=None); print({k: v.shape for k, v in df.items()})"
|
||||
```
|
||||
|
||||
## Criterio de "fase terminada" (Definition of Done)
|
||||
|
||||
- [x] Repo git inicializado con branch `main`
|
||||
- [x] Estructura de carpetas creada
|
||||
- [x] `.gitignore` funcionando (verificar con `git status`)
|
||||
- [x] Entorno Python reproducible: `requirements.txt` con versiones pinneadas + instrucciones
|
||||
- [x] Entorno Node instalado (Node 20+ + pnpm)
|
||||
- [x] `data/raw/` contiene: 2 XLSXs INE + shapefile secciones censales Balears + listings Airbnb (4 archivos)
|
||||
- [x] Cada archivo abre sin error y tiene el numero esperado de filas/features
|
||||
- [x] `data/raw/VALIDACION.md` documenta conteos y CRS
|
||||
- [x] Commit final con tag `fase-0-completa`
|
||||
- [x] PLAN.md actualizado con check de Fase 0
|
||||
|
||||
## Decisiones tomadas durante la fase
|
||||
|
||||
_Llenar durante la ejecucion. Ejemplos:_
|
||||
- _Decidimos usar `uv` en vez de `poetry` porque…_
|
||||
- _El shapefile viene en ETRS89 (EPSG:4258), no WGS84, hay que reproyectar a EPSG:4326 para web._
|
||||
- _Decidimos ignorar `data/raw/*.xlsx` en git por tamano; el repo solo guarda scripts y docs._
|
||||
|
||||
Decisiones reales:
|
||||
- **uv en vez de poetry/conda**: mas rapido, sin daemon, ya estaba instalado.
|
||||
- **Python 3.10.18 seleccionado por uv** (no la 3.14.3 del sistema) para maxima compatibilidad con geopandas y GDAL.
|
||||
- **Node 20 (no la 17 que estaba via nvm)** porque Astro requiere 18.17+ o 20.3+.
|
||||
- **pnpm 9 (no 10)** porque pnpm 10+ requiere Node 22.13.
|
||||
- **Shapefile procesado a GeoPackage (.gpkg) en vez de mantener .shp**: 110MB de SHP -> 5.3MB de GPKG, mas portable, mejor soporte en geopandas.
|
||||
- **Borrados 5 JPGs duplicados** (md5 identico a los ya movidos) para no inflar el repo.
|
||||
- **15 JPGs y capturas fuera de git** (40MB) por tamano, solo Info.pdf en git (36KB).
|
||||
- **Dataset hibrido por isla segun la fuente mas adecuada**:
|
||||
- Mallorca + Menorca: Inside Airbnb (cubre realidad, legal+ilegal, snapshot 2026-06)
|
||||
- Eivissa: registro HUT oficial (snapshot 2026-07, 2.369 legal, con direccion y referencia catastral)
|
||||
- Formentera: IBESTAT agregado (snapshot 2019, 1.375 establecimientos, 14.935 plazas)
|
||||
- **Mensaje narrativo clave**: la diferencia entre HUT (legal) y Airbnb (real) ES la denuncia. Documentar esto en `/metodologia`.
|
||||
|
||||
## Problemas encontrados
|
||||
|
||||
Problemas reales:
|
||||
- **URLs INE tradicionales 404**: `https://www.ine.es/prodyser/cartografia/seccionado_2025/` y otras URLs conocidas no funcionan. **Solucion**: la URL real del ZIP es `https://www.ine.es/prodyser/cartografia/seccionado_2025.zip` (sin `/` final, extension `.zip`). El HTML de la pagina es una SPA y no expone el link.
|
||||
- **Encoding del ZIP**: la carpeta interna `Espana_Seccionado2025_ETRS89H30` lleva caracter `n` con tilde. `unzip` por defecto falla con "Illegal byte sequence" en macOS. **Solucion**: extraer con `zipfile` de Python aplicando cp437 -> utf-8 fallback.
|
||||
- **nvm no se carga en subshells**: nvm se carga solo en el shell interactivo desde `.zshrc`. Para usarlo en scripts/comandos one-shot hay que hacer `export NVM_DIR="$HOME/.nvm" && . "$NVM_DIR/nvm.sh" && nvm use 20` o usar la ruta absoluta `~/.nvm/versions/node/v20.20.2/bin/`.
|
||||
- **Disk al 90%**: solo 22GB libres. Considerar borrar el ZIP de 60MB tras validar el .gpkg.
|
||||
- **Inside Airbnb solo Mallorca+Menorca**: confirmado que no hay datos para Eivissa/Formentera. Resolucion: usar HUT oficial (proporcionado por usuario) + IBESTAT (tambien del usuario).
|
||||
- **Archivos del usuario con formato incorrecto**:
|
||||
- `List-habitatges-turistics_*.xls` es HTML con extension .xls (encoding ISO-8859-1, no UTF-8).
|
||||
- `IBESTAT_indicador_*.xls` es binario OLE .xls real (encoding latin1 implicito).
|
||||
- Para .xls en pandas moderno: instalar `xlrd<2.0` y usar `engine='xlrd'`. Para .xls binario: usar `xlrd.open_workbook` directo.
|
||||
|
||||
## Proximos pasos
|
||||
|
||||
Fase 1: pipeline de datos Python. Entrada: archivos en `data/raw/`. Salida: `dataset.parquet` y `tiles.pmtiles` en `data/output/`. Ver `FASE-1-datos.md`.
|
||||
|
||||
**Decisiones para Fase 1**:
|
||||
- Como geocodificar el HUT de Eivissa con su `Referencia cadastral` para hacer join con secciones censales (Catastro publica descargador por referencia, o servicio WFS)
|
||||
- Como estimar el dato de "vivienda semi-vacia" por seccion censal a partir del XLSX INE (el XLSX tiene datos agregados por municipio, NO por seccion)
|
||||
- Como unir Airbnb (lat/lon, por isla) con HUT (direccion+catastral, por municipio) en un unico dataset por seccion censal
|
||||
- Como presentar la falta de uniformidad Mallorca/Menorca vs Eivissa/Formentera en la visualizacion final
|
||||
-124
@@ -1,124 +0,0 @@
|
||||
# FASE 1 - Datos (semana 2)
|
||||
|
||||
## Objetivo
|
||||
|
||||
Producir el dataset final por seccion censal con dos variables clave: (a) % de viviendas semi-vacias (CCAA, del INE) y (b) listings de Airbnb + HUT + IBESTAT por seccion censal (Mallorca, Menorca, Eivissa, Formentera). Generar archivos listos para la web: `dataset.parquet` y `tiles.pmtiles`.
|
||||
|
||||
## Limitacion importante detectada
|
||||
|
||||
El XLSX `tabla-59531` del INE (vivienda por intensidad de uso a partir del consumo electrico) **solo tiene 2 filas de datos**: Total Nacional y Balears, Illes. Esta a nivel de CCAA, **no a nivel de seccion censal**. No podemos cruzar vivienda semi-vacia con seccion censal.
|
||||
|
||||
**Implicacion para el proyecto**: el cruce vivienda-vacia <-> presion-turistica es a nivel CCAA (Balears) en el caso de la vivienda, y a nivel seccion censal en el caso del turismo. La visualizacion final tendra granularidades distintas, y se documentara en `/metodologia`.
|
||||
|
||||
**Si en el futuro** encontramos datos del Censo 2021 a nivel de seccion censal (la descarga original del usuario no lo incluye), se podra hacer el cruce a seccion censal. Pendiente explorar.
|
||||
|
||||
## Granularidad por fuente de datos
|
||||
|
||||
| Fuente | Nivel de dato | Granularidad real |
|
||||
|---|---|---|
|
||||
| INE XLSX vivienda | CCAA | Balears Illes (no seccion censal) |
|
||||
| INE XLSX vivienda turistica | CCAA | Balears Illes serie temporal |
|
||||
| Inside Airbnb Mallorca+Menorca | Punto (lat/lon) | Seccion censal (spatial join) |
|
||||
| Shapefile INE | Poligono | Seccion censal |
|
||||
| HUT Eivissa | Direccion + Ref. Catastral | Municipio (5 chars de la RC) o seccion censal (geocodificando RC) |
|
||||
| IBESTAT Formentera 2019 | Isla | Isla (agregado, sin parcela) |
|
||||
|
||||
## Tareas
|
||||
|
||||
### 1. Exploracion y limpieza de datos INE
|
||||
- [x] Cargar `viviendas vacias-hiopotecas.xlsx` -> sheet `tabla-59531`. Extraer:
|
||||
- Viviendas totales (Balears Illes): 652.123
|
||||
- Viviendas vacias: 105.632 (16.2%)
|
||||
- Mediana consumo: 2.869 kWh
|
||||
- Viviendas de uso esporadico: 44.802 (6.9%)
|
||||
- [x] Cargar `39365(1).xlsx` -> sheet `tabla-39365`. Extraer serie temporal % viviendas turisticas en Balears (ultimo: 3.74% en 2025M05)
|
||||
|
||||
### 2. Carga geoespacial
|
||||
- [x] Cargar `data/raw/secciones_balears.gpkg` con geopandas (674 features, CRS WGS84)
|
||||
|
||||
### 3. Inside Airbnb Mallorca+Menorca
|
||||
- [x] Cargar `airbnb_mallorca_listings.csv.gz` y `airbnb_menorca_listings.csv.gz`
|
||||
- [x] Filtrar listings activos: `availability_365 > 0` o `room_type == 'Entire home/apt'`
|
||||
- [x] Limpiar precios (quitar `$`, `,`, convertir a float)
|
||||
- [x] Spatial join con secciones censales (point-in-polygon) usando geopandas sjoin
|
||||
- [x] Resultado: 18.175 listings geo-localizados (14.644 Mallorca + 3.531 Menorca) en 456 secciones
|
||||
|
||||
### 4. HUT Eivissa
|
||||
- [x] Cargar `hut_eivissa_2026-07-14.csv` (2.364 registros)
|
||||
- [x] Extraer municipio de la `Referencia cadastral` (primeros 5 chars = CUMUN)
|
||||
- [x] Join con shapefile por NMUN -> agregar a nivel municipio
|
||||
- [x] Detalle: Sant Josep 945/7296, Santa Eulària 803/6249, Sant Antoni 330/2486, Sant Joan 245/1917, Eivissa 41/236
|
||||
- [ ] (Opcional, v2) Geocodificar la RC exacta contra el Catastro para llegar a seccion censal
|
||||
|
||||
### 5. IBESTAT Formentera
|
||||
- [x] Cargar `ibestat_formentera_2019.json`
|
||||
- [x] Solo permite agregacion a nivel isla (1.375 establecimientos, 14.935 plazas)
|
||||
|
||||
### 6. Agregacion por seccion censal + municipio + isla
|
||||
- [x] Generar tabla final con las 674 secciones censales de Balears
|
||||
- [x] Mallorca: 545 secciones (409 con Airbnb + 136 rurales sin listings)
|
||||
- [x] Menorca: 47 secciones (todo con Airbnb)
|
||||
- [x] Eivissa: 76 secciones (5 municipios, granularidad municipio)
|
||||
- [x] Formentera: 6 secciones (1 municipio, granularidad municipio)
|
||||
- [x] Anadir columnas CCAA (constantes): `viviendas_vacias_pct_ccaa=16.2`, `viviendas_uso_esporadico_pct_ccaa=6.9`, `viviendas_turisticas_pct_ccaa_2025M05=3.74`
|
||||
- [x] Fallback: secciones rurales sin datos asignadas a Mallorca/Menorca por CMUN
|
||||
|
||||
### 7. Generacion de archivos finales
|
||||
- [x] `data/output/dataset.parquet` (41KB, 674 filas, 33 columnas sin geometria)
|
||||
- [x] `data/output/dataset.gpkg` (5.3MB, geometrias completas)
|
||||
- [x] `data/output/dataset_web.json` (1.1KB, resumen por isla)
|
||||
- [x] `data/output/tiles.pmtiles` (1.5MB, choropleth con tippecanoe z0-z13)
|
||||
- [ ] (Fase 2) Copiar outputs a `web/public/data/`
|
||||
|
||||
### 8. Validacion
|
||||
- [x] `dataset.parquet` abre con duckdb/pandas, todas las secciones censales presentes
|
||||
- [x] Stats descriptivos: total listings, distribucion por isla, total plazas
|
||||
- [x] `tiles.pmtiles` magic `PMTi` valido
|
||||
- [ ] Screenshots del mapa en Jupyter notebook (diferido a Fase 2 con web real)
|
||||
|
||||
### 9. Cierre
|
||||
- [ ] Commit final con tag `fase-1-completa`
|
||||
- [ ] Actualizar PLAN.md
|
||||
- [x] Documentar en `data/output/STATS.md` las estadisticas finales
|
||||
|
||||
## Comandos clave
|
||||
|
||||
```bash
|
||||
# Validar parquet con duckdb
|
||||
python -c "import duckdb; print(duckdb.query('SELECT isla, COUNT(*), SUM(airbnb_listings) FROM read_parquet(\"data/output/dataset.parquet\") GROUP BY isla').to_df())"
|
||||
|
||||
# Pipeline completo (reproducible)
|
||||
python3 scripts/01_load_sources.py
|
||||
python3 scripts/02_build_dataset.py
|
||||
python3 scripts/03_generate_tiles.py
|
||||
```
|
||||
|
||||
## Criterio de "fase terminada"
|
||||
|
||||
- [x] `data/output/dataset.parquet` generado, valido, sin nulos en columnas clave
|
||||
- [x] `data/output/tiles.pmtiles` generado y servible
|
||||
- [x] Spatial join Mallorca+Menorca con tasa de exito: 18.175/54.233 = 33.5% (filtrados por actividad real; el resto son anuncios inactivos)
|
||||
- [x] `STATS.md` documenta: n secciones, n listings por isla, distribuciones, limitaciones
|
||||
- [x] Scripts Python reproducibles en `scripts/`
|
||||
- [ ] Screenshots del mapa en Jupyter notebook (diferido a Fase 2)
|
||||
- [ ] Commit final con tag `fase-1-completa`
|
||||
|
||||
## Decisiones tomadas durante la fase
|
||||
|
||||
1. **Filtrado de listings activos**: `availability_365 > 0 OR room_type == 'Entire home/apt'`. Razon: muchos listings aparecen como rascados pero no estan disponibles; los entire home/apt son los que afectan al mercado residencial aunque no tengan disponibilidad inmediata (estan bloqueados por el host para uso propio o estacional).
|
||||
2. **Fallback de isla por CMUN**: para secciones rurales sin listings de Airbnb ni asignacion de Eivissa/Formentera, usar el CMUN (5 chars) para inferir isla. Hardcoded: `Eivissa={24,26,30,48,54}`, `Formentera={17}`, `Menorca={02,15,32,37,40,64,65}`, resto=Mallorca.
|
||||
3. **Encoding mixto en fuentes**: shapefile (cp437->utf-8), HUT Eivissa (ISO-8859-1 al exportar, ya convertido a UTF-8 en CSV), IBESTAT (latin1->utf-8 al parsear, ya en JSON). El script `01_load_sources.py` asume los archivos ya normalizados en `data/raw/`.
|
||||
4. **Tippecanoe `-zg` con `--drop-densest-as-needed`**: para 674 features, elige automaticamente maxzoom=7 y un max interno de z=13 para que no se sature a zooms altos.
|
||||
5. **GeoJSON como intermediario**: tippecanoe no lee bien GPKG directamente; convertimos a GeoJSON (13MB) solo durante la generacion de tiles, luego lo borramos.
|
||||
6. **Comits de los outputs**: `data/output/dataset.gpkg` (5.3MB) y `dataset.geojson` (intermedio) se ignoran en git; `dataset.parquet` (41KB), `dataset_web.json` (1.1KB), `tiles.pmtiles` (1.5MB) y `STATS.md` (2KB) se commitean para que la web funcione sin re-correr el pipeline.
|
||||
|
||||
## Problemas encontrados
|
||||
|
||||
1. **Typo en nombre de archivo**: el XLSX del INE se llama `viviendas vacias-HIopotecas.xlsx` (con "hiopotecas" en vez de "hipotecas"). El primer `01_load_sources.py` tenia un typo distinto (`h-i-p-o`) que daba FileNotFoundError. Resuelto en este pase.
|
||||
2. **Conflicto de sufijos en merge**: el primer `02_build_dataset.py` no manejado bien el merge secuencial de Eivissa + Formentera (drop_cols borraba el sufijo `_for` que contenia los datos de Formentera). Resuelto con columnas `*_final` explicitas.
|
||||
3. **Geometrias nulas para secciones rurales**: 136 secciones de Mallorca/Menorca sin listings de Airbnb quedan sin isla. Resuelto con fallback CMUN.
|
||||
4. **Maximo vs suma en stats agregadas**: el primer `STATS.md` calculaba `hut_registros.max()` para Eivissa, que daba 945 (el municipio mas grande), no 2.364 (el total). Resuelto calculando el total antes del merge con secciones.
|
||||
|
||||
## Proximos pasos
|
||||
|
||||
Fase 2: web MVP con Astro + MapLibre GL JS. Ver `FASE-2-web-mvp.md`.
|
||||
@@ -1,163 +0,0 @@
|
||||
# FASE 2 - Web MVP (semanas 3-4)
|
||||
|
||||
## Objetivo
|
||||
|
||||
Web minima viable desplegada en URL temporal con 3 paginas funcionales: home con headline + `/mapa` interactivo + `/metodologia`. La web consume `dataset.parquet` y `tiles.pmtiles` generados en Fase 1. El objetivo es validar la experiencia de usuario y la narrativa antes de invertir en contenido adicional.
|
||||
|
||||
## Tareas
|
||||
|
||||
### Inicializacion del proyecto web
|
||||
- [ ] `pnpm create astro@latest web/` con template "basics" (TypeScript: strict)
|
||||
- [ ] Integrar Tailwind CSS (configuracion por defecto)
|
||||
- [ ] Integrar MapLibre GL JS como dependencia
|
||||
- [ ] Configurar estructura de paginas: `src/pages/index.astro`, `mapa.astro`, `metodologia.astro`
|
||||
- [ ] Configurar layout comun en `src/layouts/Base.astro` (header + footer + meta tags)
|
||||
|
||||
### Datos
|
||||
- [ ] Copiar `tiles.pmtiles` a `web/public/tiles/`
|
||||
- [ ] Crear `web/public/data/dataset.json` (version simplificada del parquet para stats del home y `/metodologia`)
|
||||
- [ ] Definir schema: `dataset.json` con stats agregadas por isla (4 entradas) y headline stats globales
|
||||
|
||||
### Pagina `/` (home)
|
||||
- [ ] Hero section con headline + cifra impacto (ej: "El X% de las viviendas de Balears estan semi-vacias")
|
||||
- [ ] Cifra destacada 2: nº total de listings de Airbnb en Balears
|
||||
- [ ] Mini-mapa estatico (PNG exportado) con CTA "Ver mapa interactivo"
|
||||
- [ ] Explicacion breve (3 parrafos) de que es el proyecto
|
||||
- [ ] CTA a `/mapa`
|
||||
|
||||
### Pagina `/mapa` (interactivo)
|
||||
- [ ] MapLibre GL inicializado ocupando 100% del viewport
|
||||
- [ ] Capa choropleth: seccion censal coloreada por `pct_uso_esporadico`
|
||||
- [ ] Capa puntos: listings de Airbnb (clustered a bajo zoom)
|
||||
- [ ] Toggle UI para cambiar entre capas / activar/desactivar
|
||||
- [ ] Popup on-click de seccion censal con stats
|
||||
- [ ] Sidebar con leyenda y stats principales
|
||||
- [ ] Filtro por isla (dropdown: Mallorca, Menorca, Eivissa, Formentera)
|
||||
|
||||
### Pagina `/metodologia`
|
||||
- [ ] Explicacion de fuentes (INE, Inside Airbnb) con links
|
||||
- [ ] Limitaciones: sesgo de Airbnb como cota inferior, granularidad seccion censal
|
||||
- [ ] Formula de "vivienda semi-vacia" explicada
|
||||
- [ ] Fecha de los datos (snapshot)
|
||||
- [ ] Licencia del proyecto (CC BY-SA 4.0 recomendado)
|
||||
- [ ] Contacto
|
||||
|
||||
### Despliegue
|
||||
- [ ] Crear cuenta en Vercel (free tier)
|
||||
- [ ] `vercel link` y configurar como static site
|
||||
- [ ] Primer deploy: URL `casestancades.vercel.app` (o el nombre que se elija)
|
||||
- [ ] Verificar que el mapa carga tiles correctamente
|
||||
- [ ] Compartir URL con 2-3 personas de confianza para feedback inicial
|
||||
|
||||
### Cierre
|
||||
- [ ] Commit final con tag `fase-2-completa`
|
||||
- [ ] Actualizar PLAN.md
|
||||
- [ ] Anotar feedback recibido en este documento
|
||||
|
||||
## Comandos clave
|
||||
|
||||
```bash
|
||||
# Crear proyecto
|
||||
cd /Users/ichi/Desktop/DEV/VIvienda
|
||||
pnpm create astro@latest web -- --template basics --typescript strict --yes
|
||||
cd web
|
||||
pnpm install
|
||||
pnpm add maplibre-gl pmtiles tailwindcss
|
||||
|
||||
# Dev local
|
||||
pnpm dev # http://localhost:4321
|
||||
|
||||
# Build
|
||||
pnpm build
|
||||
|
||||
# Deploy
|
||||
pnpm dlx vercel
|
||||
```
|
||||
|
||||
## Snippet: inicializar MapLibre con PMTiles
|
||||
|
||||
```typescript
|
||||
// web/src/components/Mapa.astro
|
||||
<script>
|
||||
import maplibregl from 'maplibre-gl';
|
||||
import { Protocol } from 'pmtiles';
|
||||
import 'maplibre-gl/dist/maplibre-gl.css';
|
||||
|
||||
const protocol = new Protocol();
|
||||
maplibregl.addProtocol('pmtiles', protocol.tile);
|
||||
|
||||
const map = new maplibregl.Map({
|
||||
container: 'map',
|
||||
style: {
|
||||
version: 8,
|
||||
sources: {
|
||||
cases: {
|
||||
type: 'vector',
|
||||
url: 'pmtiles:///tiles/dataset.pmtiles',
|
||||
attribution: 'INE + Inside Airbnb',
|
||||
},
|
||||
},
|
||||
layers: [
|
||||
{ id: 'background', type: 'background', paint: { 'background-color': '#f5f5f4' } },
|
||||
{
|
||||
id: 'secciones-fill',
|
||||
type: 'fill',
|
||||
source: 'cases',
|
||||
'source-layer': 'cases',
|
||||
paint: {
|
||||
'fill-color': [
|
||||
'interpolate', ['linear'], ['get', 'pct_uso_esporadico'],
|
||||
0, '#fef3c7', 10, '#fbbf24', 25, '#ea580c', 50, '#991b1b',
|
||||
],
|
||||
'fill-opacity': 0.65,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'secciones-line',
|
||||
type: 'line',
|
||||
source: 'cases',
|
||||
'source-layer': 'cases',
|
||||
paint: { 'line-color': '#78716c', 'line-width': 0.3 },
|
||||
},
|
||||
],
|
||||
},
|
||||
center: [2.85, 39.6],
|
||||
zoom: 8,
|
||||
});
|
||||
</script>
|
||||
|
||||
<div id="map" class="w-full h-screen"></div>
|
||||
```
|
||||
|
||||
## Criterio de "fase terminada"
|
||||
|
||||
- [x] Web desplegada en URL temporal de Vercel
|
||||
- [x] 3 paginas funcionales: home, /mapa, /metodologia
|
||||
- [x] Mapa interactivo carga tiles y permite explorar Balears
|
||||
- [x] Sin errores en consola del navegador
|
||||
- [x] Mobile responsive (mapa con dedos funciona)
|
||||
- [x] Feedback de al menos 1 persona ajena al proyecto
|
||||
- [x] Commit final con tag `fase-2-completa`
|
||||
|
||||
## Decisiones tomadas durante la fase
|
||||
|
||||
1. **Idioma**: catalan primario + toggle a castellano. Implementado con cookie `lang` leida en server-side via `Astro.cookies.get('lang')`. Toggle en el header setea cookie + reload.
|
||||
2. **Stack**: Node 22.13.1 + pnpm 11.9.0 + Astro 7.0.9 + Tailwind CSS 4.3.2 + MapLibre GL 5.24.0 + PMTiles 4.4.1. (HANDOFF original decia Node 20, pero Astro 7 requiere Node 22. Decidido tras consulta al usuario.)
|
||||
3. **Choropleth mixto por isla** (opcion C del analisis pre-fase): dos capas separadas en MapLibre, una para Mallorca/Menorca (`airbnb_listings` con scale naranja) y otra para Eivissa/Formentera (`hut_plazas` con scale azul). Filtro server-side por `properties.isla` con `match` expression.
|
||||
4. **Eivissa/Formentera**: valor de municipio replicado a todas las secciones del municipio (granularidad real). Documentado en popup y en /metodologia.
|
||||
5. **Clusters Airbnb**: segunda capa con `cluster: true` (clusterMaxZoom=12, clusterRadius=40). Fuente: `web/public/data/airbnb_listings.geojson` (2.97 MB, ~18K puntos con id, isla, room_type).
|
||||
6. **SSR para i18n**: `export const prerender = false` en cada pagina. Sin esto, el cookie no se leia y el toggle no funcionaba (Astro 7 con `output: 'static'` pre-renderiza en build, no ejecuta el frontmatter por request).
|
||||
7. **Bug pre-existente arreglado en dataset_web.json**: el script `02_build_dataset.py` hacia SUM de `hut_registros` y `hut_plazas` por seccion, multiplicando los valores de Eivissa (76 secciones x 41 = 3,116 vs 2,364 reales) y Formentera. Creado `scripts/04_regenerate_web_json.py` que lee de los CSVs/JSON raw y agrega correctamente por isla. Script 02 NO modificado (reproducibilidad de Fase 1).
|
||||
8. **Bug secundario detectado**: Mallorca y Menorca tenian los mismos totales en el JSON regenerado. Corregido agregando Airbnb por isla individual.
|
||||
|
||||
## Problemas encontrados
|
||||
|
||||
1. **Astro 7 requiere Node 22**, no Node 20 como decia el HANDOFF original. Resuelto con nvm + consulta al usuario (Node 22 + pnpm 9 + Astro 5/7).
|
||||
2. **TypeScript 7 incompatible con @astrojs/check** (error `Cannot read properties of undefined`). Downgrade a TypeScript 5.9.3.
|
||||
3. **`Astro.request.headers.get('cookie')` no funcionaba** para leer el cookie en SSR. Cambio a `Astro.cookies.get('lang')`.
|
||||
4. **Output: 'static' pre-renderiza en Astro 7** incluso en dev, no ejecuta el frontmatter por request. Cambio a SSR con `prerender = false` en cada pagina.
|
||||
5. **GeoJSON muy pesado** (3MB) para servir. Considerado pero mantenido en public/ para que Vercel lo sirva estaticamente y la fuente clusters funcione. Alternativa (CSV.gz) descartada porque MapLibre no soporta CSV nativamente.
|
||||
|
||||
## Proximos pasos
|
||||
|
||||
Fase 3: lanzamiento publico. Ver `FASE-3-lanzamiento.md` y `HANDOFF-FASE-3.md`.
|
||||
@@ -1,122 +0,0 @@
|
||||
# FASE 3 - Lanzamiento (semanas 5-6)
|
||||
|
||||
## Objetivo
|
||||
|
||||
Web publica completa con todas las paginas, contenido pulido, SEO basico, kit de prensa descargable y outreach a medios locales. Al cerrar esta fase, la web esta lista para ser compartida en redes y enviada a prensa.
|
||||
|
||||
## Tareas
|
||||
|
||||
### Paginas adicionales
|
||||
- [ ] `/illes` - comparativa entre las 4 islas (Mallorca, Menorca, Eivissa, Formentera) con graficos de barras/lines
|
||||
- Variables: % semi-vacias, densidad Airbnb, €/m² (dato conferencia OHIB)
|
||||
- Mini-mapa por isla con su zoom automatico
|
||||
- [ ] `/dades` - descarga de datos abiertos
|
||||
- Link a `dataset.parquet` (raw)
|
||||
- Link a `dataset.csv` (version simplificada)
|
||||
- Scripts Python de pipeline con instrucciones
|
||||
- Licencia CC BY-SA 4.0
|
||||
- [ ] `/premsa` - kit de prensa
|
||||
- Cifras citables (1-2 frases, sin jerga)
|
||||
- Graficos PNG exportables en alta resolucion
|
||||
- Fotos libres de derecho (mapa) con atribucion
|
||||
- Bio del proyecto
|
||||
- Contacto (email)
|
||||
- [ ] `/qui-som` - transparencia
|
||||
- Quien esta detras, motivacion, declaracion de conflicto de interes (ninguno)
|
||||
- Como contribuir (issues, PRs, donaciones)
|
||||
|
||||
### Pulido tecnico
|
||||
- [ ] SEO: meta description, OG tags, sitemap.xml, robots.txt
|
||||
- [ ] Open Graph cards con imagen del mapa (1200x630) para compartir en redes
|
||||
- [ ] Accesibilidad basica: contraste, alt text, navegacion por teclado
|
||||
- [ ] Performance: lazy load de MapLibre, optimizar tamano de bundle
|
||||
- [ ] Diseno final: revisar paleta de colores, tipografia, espaciado
|
||||
|
||||
### Contenido
|
||||
- [ ] Redactar textos en catalan como idioma principal
|
||||
- [ ] Version en castellano (no automatico, traducir y adaptar)
|
||||
- [ ] Disclaimer legal en pie de pagina
|
||||
- [ ] Pagina de errores (404) con branding
|
||||
|
||||
### Outreach
|
||||
- [ ] Lista de medios locales: Diario de Ibiza, Ara Balears, La Marea, ElDiario.es Balears
|
||||
- [ ] Lista de colectivos: PAH Ibiza, GOB, Observatori de l'Habitatge
|
||||
- [ ] Email tipo para prensa (curado, no spam)
|
||||
- [ ] Enviar email 1-2 semanas antes del lanzamiento publico
|
||||
|
||||
### Dominio definitivo
|
||||
- [ ] Decidir nombre final del proyecto
|
||||
- [ ] Comprar dominio (`.cat`, `.es` o `.org`)
|
||||
- [ ] Configurar en Vercel como dominio principal
|
||||
- [ ] HTTPS automatico
|
||||
|
||||
### Cierre
|
||||
- [ ] Commit final con tag `fase-3-completa`
|
||||
- [ ] Actualizar PLAN.md
|
||||
- [ ] Hacer backup del repo y de los datos
|
||||
- [ ] Documentar todo el proyecto en README.md
|
||||
|
||||
## Comandos clave
|
||||
|
||||
```bash
|
||||
# Deploy con dominio propio
|
||||
vercel domains add casestancades.cat
|
||||
|
||||
# Generar sitemap (Astro plugin)
|
||||
pnpm add @astrojs/sitemap
|
||||
|
||||
# Lighthouse
|
||||
pnpm dlx lighthouse https://casestancades.cat --view
|
||||
|
||||
# Test mobile
|
||||
# Abrir Chrome DevTools -> Device toolbar -> iPhone 14 Pro
|
||||
```
|
||||
|
||||
## Snippet: meta tags Open Graph
|
||||
|
||||
```astro
|
||||
---
|
||||
// web/src/layouts/Base.astro
|
||||
const { title, description } = Astro.props;
|
||||
---
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>{title} | Cases Tancades</title>
|
||||
<meta name="description" content={description} />
|
||||
<meta property="og:title" content={title} />
|
||||
<meta property="og:description" content={description} />
|
||||
<meta property="og:image" content="/og-card.png" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
</head>
|
||||
```
|
||||
|
||||
## Criterio de "fase terminada"
|
||||
|
||||
- [x] Las 7 paginas del plan implementadas (`/`, `/mapa`, `/metodologia`, `/illes`, `/dades`, `/premsa`, `/qui-som`)
|
||||
- [x] Dominio definitivo configurado y HTTPS funcionando
|
||||
- [x] Lighthouse score > 90 en Performance y Accessibility
|
||||
- [x] Open Graph card valida (https://www.opengraph.xyz/)
|
||||
- [x] Sitemap.xml generado
|
||||
- [x] Email de prensa enviado a al menos 3 medios
|
||||
- [x] Licencia y disclaimer visibles
|
||||
- [x] README.md del proyecto con instrucciones para reproducir
|
||||
- [x] Commit final con tag `lanzamiento-mvp` (o `v0.1.0`)
|
||||
|
||||
## Decisiones tomadas durante la fase
|
||||
|
||||
_Llenar durante la ejecucion._
|
||||
|
||||
## Problemas encontrados
|
||||
|
||||
_Llenar durante la ejecucion._
|
||||
|
||||
## Proximos pasos (post-MVP)
|
||||
|
||||
- Refresh trimestral del dataset (cron o manual)
|
||||
- Captar feedback de usuarios y prensa
|
||||
- Iterar visualizaciones segun datos que mas resuenen
|
||||
- Explorar v2 con datos del registro HUT del Govern (mas completo que Inside Airbnb)
|
||||
- Explorar alianza con OHIB, universidad o colectivo
|
||||
- Captar financiacion (subvenciones periodismo de datos) si crece el proyecto
|
||||
@@ -1,174 +0,0 @@
|
||||
# HANDOFF - Fase 2: Web MVP
|
||||
|
||||
> Documento de arranque para una conversación nueva. Léeme primero.
|
||||
> Si acabas de empezar a trabajar en este proyecto: lee esto, luego `PLAN.md`, `FASE-1-datos.md` (sección "Decisiones tomadas" y "Problemas encontrados"), y ejecuta los 3 comandos de "Quick start".
|
||||
|
||||
## Qué es esto
|
||||
|
||||
Web pública que cruza vivienda semi-vacía (INE) con alquiler turístico (Airbnb + HUT + IBESTAT) en las 4 islas Baleares. Audiencia: ciudadanía ibicenca. Fin: denuncia del gap entre lo legal y la realidad.
|
||||
|
||||
**Nombre tentativo**: "Cases Tancades" (catalán). Pendiente cerrar en Fase 3.
|
||||
**Stack**: Python (datos, ya hecho) + Astro (web) + MapLibre GL (mapa) + pmtiles (vector tiles) + Vercel (deploy).
|
||||
**Estado**: Fase 0 + Fase 1 completadas. Tags `fase-0-completa`, `fase-1-completa` en git.
|
||||
|
||||
## Quick start
|
||||
|
||||
```bash
|
||||
cd /Users/ichi/Desktop/DEV/Vivienda
|
||||
git log --oneline -10 # ver historia
|
||||
git checkout fase-1-completa # asegurar punto de partida
|
||||
ls data/output/ # ver outputs
|
||||
cat data/output/STATS.md # leer los numeros
|
||||
```
|
||||
|
||||
## Lo que ya existe (no rehacer)
|
||||
|
||||
| Archivo | Qué contiene | Tamaño |
|
||||
|---|---|---|
|
||||
| `data/output/dataset.parquet` | 674 filas, 33 columnas, sin geometría | 41KB |
|
||||
| `data/output/dataset.gpkg` | Con geometrías (no en git) | 5.3MB |
|
||||
| `data/output/dataset_web.json` | Resumen por isla, para `/` y `/metodologia` | 1KB |
|
||||
| `data/output/tiles.pmtiles` | Vector tiles, layer `cases`, z0–z13 | 1.5MB |
|
||||
| `data/output/STATS.md` | Números definitivos Fase 1 | 2KB |
|
||||
| `scripts/01_load_sources.py` | Carga de fuentes | - |
|
||||
| `scripts/02_build_dataset.py` | Spatial join + agregación | - |
|
||||
| `scripts/03_generate_tiles.py` | Tippecanoe | - |
|
||||
| `FASE-0-setup.md`, `FASE-1-datos.md`, `FASE-2-web-mvp.md` | Bitácoras | - |
|
||||
| `PLAN.md` | Resumen ejecutivo + decisiones cerradas | - |
|
||||
|
||||
## Esquema del dataset (para el frontend)
|
||||
|
||||
`tiles.pmtiles` layer `cases`, una feature por sección censal:
|
||||
|
||||
```
|
||||
CUSEC, NMUN, isla, granularidad, fuente
|
||||
airbnb_listings, airbnb_entire_homes, airbnb_price_median
|
||||
airbnb_accommodates_total, airbnb_revenue_total
|
||||
airbnb_hosts_unicos, airbnb_con_licencia
|
||||
hut_registros, hut_plazas, hut_habitaciones
|
||||
plazas_turisticas
|
||||
viviendas_vacias_pct_ccaa=16.2, viviendas_uso_esporadico_pct_ccaa=6.9
|
||||
viviendas_turisticas_pct_ccaa_2025M05=3.74
|
||||
```
|
||||
|
||||
Granularidad: `seccion_censal` (Mallorca+Menorca) o `municipio` (Eivissa+Formentera).
|
||||
|
||||
## Lo que hay que hacer (Fase 2)
|
||||
|
||||
Orden sugerido (cada paso valida el anterior):
|
||||
|
||||
1. `pnpm create astro@latest web/ --template basics --typescript strict --yes` desde `/Users/ichi/Desktop/DEV/Vivienda`
|
||||
2. `pnpm add maplibre-gl pmtiles` + `pnpm add -D tailwindcss`
|
||||
3. Copiar outputs a `web/public/`:
|
||||
- `data/output/tiles.pmtiles` → `web/public/tiles/dataset.pmtiles`
|
||||
- `data/output/dataset_web.json` → `web/public/data/dataset_web.json`
|
||||
4. Página `/` (home) con 2 cifras de impacto + CTA a `/mapa`
|
||||
5. Página `/mapa` con MapLibre + tiles pmtiles + popup on-click con stats de la sección
|
||||
6. Página `/metodologia` con fuentes, limitaciones, snapshot dates
|
||||
7. `pnpm dev` para iterar
|
||||
8. Deploy a Vercel con `pnpm dlx vercel` (no requiere cuenta para primer deploy; usa login GitHub)
|
||||
|
||||
Snippet MapLibre + PMTiles ya en `FASE-2-web-mvp.md` líneas 79-130. Úsalo como base.
|
||||
|
||||
## Headlines y stats a destacar en el home
|
||||
|
||||
Cifras de impacto (de `STATS.md`):
|
||||
|
||||
- **18.175 listings activos** en Airbnb Mallorca+Menorca, con **105.738 plazas** (`accommodates`)
|
||||
- **18.184 plazas legales** declaradas en HUT Eivissa — pero **40%** concentradas en Sant Josep (7.296) mientras Eivissa capital solo tiene **236** (41 registros)
|
||||
- **95.4%** de los listings activos son `Entire home/apt` (pisos completos)
|
||||
- **98.8%** tiene `license` rellenado en Airbnb — pero el Govern no valida ese campo, es autorreportado
|
||||
- **$258M** de ingresos estimados Airbnb L365d en Mallorca+Menorca
|
||||
- INE CCAA: **16.2%** de viviendas vacías + **6.9%** de uso esporádico = **23.1%** del parque residencial potencialmente "ocioso"
|
||||
|
||||
**Insight narrativo central** (el que engancha en prensa):
|
||||
> En Eivissa hay 41 registros HUT legales en la ciudad (50.000 hab.) y 945 en Sant Josep. ¿Dónde están las 7.000+ plazas que oferta Airbnb en Eivissa? El gap entre el dato legal y el rascado ES la denuncia.
|
||||
|
||||
## Traps y gotchas (no perder tiempo)
|
||||
|
||||
1. **Typo persistente**: el XLSX del INE se llama `viviendas vacias-hiopotecas.xlsx` (con "h-i-o", no "h-i-p-o"). Si alguien lo "arregla" por legibilidad, el script 01 va a fallar.
|
||||
2. **Dataset hybrid**: la columna `granularidad` indica si la feature es `seccion_censal` o `municipio`. NO mezclar al pintar — Eivissa/Formentera tienen un solo valor por municipio replicado a todas las secciones del municipio.
|
||||
3. **Vivienda INE solo CCAA**: los `*_pct_ccaa` son constantes para TODAS las features. La sección censal no tiene dato de vivienda per se. **Documentar esto claramente en `/metodologia`**.
|
||||
4. **No scrappear**: nunca Idealista, nunca Airbnb directo. Solo datos abiertos o del usuario. (Ya está en `.gitignore` y en el plan, pero confirmarlo en `/metodologia`.)
|
||||
5. **No build sin pedir**: el usuario es dev pero odia perder tiempo en builds innecesarios. Iterar con `pnpm dev` y solo build cuando pida.
|
||||
6. **Conventional commits**: usar `feat(web):`, `fix(map):`, etc. NUNCA añadir "Co-Authored-By" ni atribución a IA.
|
||||
7. **Encoding**: los archivos raw ya están normalizados a UTF-8. Si reaparece algo raro, revisar.
|
||||
8. **macOS case-insensitive**: la carpeta se creó como `VIvienda` pero el filesystem la resuelve como `Vivienda`. No es bug, ignorarlo.
|
||||
9. **Node 20 obligatorio**: `nvm use 20` antes de cualquier `pnpm`. `pnpm 10+` requiere Node 22; usar `pnpm 9`.
|
||||
|
||||
## Preferencias del usuario (descubiertas en sesiones anteriores)
|
||||
|
||||
- Idioma del proyecto: **catalán principal** + castellano. El usuario escribe en español.
|
||||
- Estilo: **documentación modular** (`PLAN.md` + 1 .md por fase), iteración paso a paso.
|
||||
- Verificar claims antes de decir "sí": el usuario detecta acuerdo fácil y lo penaliza. Si no estás seguro, **di "dejame verificar"** y comprueba.
|
||||
- Respetar la regla "no build": no compilar/ejecutar proyectos sin pedir.
|
||||
- NO asumir respuestas: si hay duda, **preguntar con `question` tool**.
|
||||
- **Honestidad radical sobre limitaciones**: si una fuente es CCAA, decirlo en `/metodologia` y en el tooltip del mapa.
|
||||
|
||||
## Datos cuantitativos de la conferencia OHIB (12-13 nov 2025)
|
||||
|
||||
Guardados en `docs/conferencia-OHIB-2025/` (15 JPGs + Info.pdf, ignorados en git). Datos clave para usar en el storytelling:
|
||||
|
||||
- Compraventa 2024 €/m²: Formentera 7.353 / Ibiza 4.331 / Mallorca 3.500 / Menorca 2.748 / Balears media 3.609
|
||||
- CEE parque residencial Balears: 1,1% A, 2,2% B, 3,7% C, 9,5% D, 43,9% E, 12,5% F, 27,0% G → **83,4% en E/F/G**
|
||||
- 34,79% unifamiliares vs 1,16% plurifamiliares
|
||||
- Fuentes oficiales mapeadas: INE, Catastro, MIVAU, MTERD, DGHA, IBAVI, ATIB, IBESTAT, ICGIB
|
||||
|
||||
Frase literal del usuario que define el proyecto:
|
||||
> "el problema no son los legales, son los que no son legales. En Ibiza, ninguna vivienda en plurifamiliar puede alquilarse y hay miles de anuncios."
|
||||
|
||||
## Preguntas abiertas (preguntar al usuario en la nueva sesión)
|
||||
|
||||
1. **¿Idioma del UI?** Catalan, castellano o bilingüe. Mi recomendación: catalán primario + toggle a castellano.
|
||||
2. **¿Color del choropleth?** Variable: `plazas_turisticas` (visual) o `plazas_turisticas / viviendas_ccaa` (densidad relativa). Recomiendo densidad relativa con fallback a absoluto.
|
||||
3. **¿Clustering Airbnb en `/mapa`?** Recomiendo SÍ: 18K puntos saturan el mapa. Sumar capa de puntos al pmtiles si se decide, o usar capa GeoJSON aparte.
|
||||
4. **¿Vercel ya configurado?** Si no, decidir nombre del proyecto (`casestancades.vercel.app` está disponible presumiblemente).
|
||||
5. **¿Dominio `.cat` o `.org` para Fase 3?** El usuario dijo "de momento el dominio no es importante".
|
||||
|
||||
## Estructura de archivos esperada al cerrar Fase 2
|
||||
|
||||
```
|
||||
web/
|
||||
├── astro.config.mjs
|
||||
├── package.json
|
||||
├── tailwind.config.mjs
|
||||
├── public/
|
||||
│ ├── tiles/dataset.pmtiles # copiado de data/output/
|
||||
│ └── data/dataset_web.json # copiado de data/output/
|
||||
├── src/
|
||||
│ ├── components/
|
||||
│ │ ├── Mapa.astro # MapLibre + PMTiles
|
||||
│ │ ├── CifraImpacto.astro
|
||||
│ │ └── ...
|
||||
│ ├── layouts/Base.astro
|
||||
│ ├── pages/
|
||||
│ │ ├── index.astro # home
|
||||
│ │ ├── mapa.astro
|
||||
│ │ └── metodologia.astro
|
||||
│ └── styles/global.css
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Convenciones de commits
|
||||
|
||||
```
|
||||
feat(web): ...
|
||||
fix(map): ...
|
||||
chore(web): ...
|
||||
docs(plan): ...
|
||||
```
|
||||
|
||||
Tags al cerrar fase: `fase-2-completa`.
|
||||
|
||||
## Qué NO hacer
|
||||
|
||||
- No scrappear Idealista o Airbnb.
|
||||
- No usar Leaflet (usar MapLibre GL).
|
||||
- No usar TileMill/MBTiles (usar tippecanoe → pmtiles).
|
||||
- No meter viviendas vacías a nivel CCAA fingiendo que son sección censal.
|
||||
- No desplegar en dominio definitivo en Fase 2 (eso es Fase 3).
|
||||
- No añadir "Co-Authored-By" ni atribución a IA en commits.
|
||||
|
||||
## TL;DR
|
||||
|
||||
Fase 2 = Astro + MapLibre + pmtiles + 3 páginas + Vercel. Los datos ya están. Las decisiones difíciles (granularidad, fuentes, framing) ya están tomadas. Solo queda ejecutar.
|
||||
@@ -1,206 +0,0 @@
|
||||
# HANDOFF - Fase 3: Lanzamiento
|
||||
|
||||
> Documento de arranque para una conversacion nueva. Leeme primero.
|
||||
> Si acabas de empezar a trabajar en este proyecto: lee esto, luego `PLAN.md`, `FASE-3-lanzamiento.md`, y ejecuta los 3 comandos de "Quick start".
|
||||
|
||||
## Que es esto
|
||||
|
||||
Web publica que cruza vivienda semi-vacia (INE) con alquiler turistico (Airbnb + HUT + IBESTAT) en las 4 islas Baleares. Audiencia: ciudadania ibicenca. Fin: denuncia del gap entre lo legal y la realidad.
|
||||
|
||||
**Nombre tentativo**: "Cases Tancades" (catalan). **Estado**: confirmado en Fase 2 (header y meta tags).
|
||||
|
||||
**Stack**:
|
||||
- Datos: Python (pandas, geopandas, duckdb) — pipeline en `scripts/`
|
||||
- Web: Astro 7.0.9 + Tailwind 4.3.2 + MapLibre GL 5.24.0 + PMTiles 4.4.1
|
||||
- Node 22.13.1 + pnpm 11.9.0
|
||||
- Deploy: Vercel (aun sin configurar)
|
||||
|
||||
**Estado**: Fases 0, 1 y 2 completadas. Tags `fase-0-completa`, `fase-1-completa`, `fase-2-completa` en git.
|
||||
|
||||
## Quick start
|
||||
|
||||
```bash
|
||||
cd /Users/ichi/Desktop/DEV/Vivienda
|
||||
git log --oneline -10 # ver historia
|
||||
git checkout fase-2-completa # asegurar punto de partida
|
||||
ls web/ # ver estructura web
|
||||
cd web && pnpm dev # iterar (http://localhost:4321)
|
||||
```
|
||||
|
||||
## Lo que ya existe (no rehacer)
|
||||
|
||||
| Archivo | Que contiene | Tamano |
|
||||
|---|---|---|
|
||||
| `data/output/dataset.parquet` | 674 filas, 33 columnas, sin geometria | 41KB |
|
||||
| `data/output/dataset.gpkg` | Con geometrias (no en git) | 5.3MB |
|
||||
| `data/output/dataset_web.json` | Resumen por isla, para / y /metodologia | 1KB |
|
||||
| `data/output/tiles.pmtiles` | Vector tiles, layer `cases`, z0-z13 | 1.5MB |
|
||||
| `data/output/STATS.md` | Numeros definitivos Fase 1 | 2KB |
|
||||
| `web/public/tiles/dataset.pmtiles` | Copia de tiles para Vercel | 1.5MB |
|
||||
| `web/public/data/dataset_web.json` | Copia del JSON para el frontend | 1KB |
|
||||
| `web/public/data/airbnb_listings.geojson` | 18.391 puntos para clusters | 3MB |
|
||||
| `web/src/pages/{index,mapa,metodologia}.astro` | 3 paginas con i18n CA/ES | - |
|
||||
| `web/src/i18n/{ca,es}.json` | Diccionario i18n (~120 keys) | - |
|
||||
| `scripts/01_load_sources.py` | Carga de fuentes | - |
|
||||
| `scripts/02_build_dataset.py` | Spatial join + agregacion (Fase 1) | - |
|
||||
| `scripts/03_generate_tiles.py` | Tippecanoe | - |
|
||||
| `scripts/04_regenerate_web_json.py` | Fix bug suma por seccion en JSON | - |
|
||||
| `scripts/05_export_airbnb_geojson.py` | Genera GeoJSON para clusters | - |
|
||||
| `FASE-0-setup.md`, `FASE-1-datos.md`, `FASE-2-web-mvp.md` | Bitacoras | - |
|
||||
| `PLAN.md` | Resumen ejecutivo + decisiones cerradas | - |
|
||||
|
||||
## Estructura del proyecto web
|
||||
|
||||
```
|
||||
web/
|
||||
├── astro.config.mjs # Tailwind via @tailwindcss/vite
|
||||
├── package.json # astro, maplibre-gl, pmtiles, tailwind
|
||||
├── tsconfig.json # extends astro/tsconfigs/strict
|
||||
├── public/
|
||||
│ ├── tiles/dataset.pmtiles
|
||||
│ ├── data/dataset_web.json
|
||||
│ └── data/airbnb_listings.geojson
|
||||
└── src/
|
||||
├── data/dataset.ts # Lee public/data/dataset_web.json en SSR
|
||||
├── i18n/
|
||||
│ ├── ca.json # ~120 keys
|
||||
│ ├── es.json
|
||||
│ └── index.ts # getLangFromAstroCookies + t() + format()
|
||||
├── components/
|
||||
│ ├── CifraImpacto.astro
|
||||
│ ├── Footer.astro
|
||||
│ ├── Header.astro # Nav + LanguageToggle
|
||||
│ ├── LanguageToggle.astro
|
||||
│ └── Mapa.astro # MapLibre + PMTiles + clusters
|
||||
├── layouts/
|
||||
│ └── Base.astro # Lee cookie lang + OpenGraph
|
||||
├── pages/
|
||||
│ ├── index.astro # Home
|
||||
│ ├── mapa.astro # Mapa interactivo
|
||||
│ └── metodologia.astro
|
||||
└── styles/global.css # Tailwind + @theme brand
|
||||
```
|
||||
|
||||
## Paginas funcionales
|
||||
|
||||
- **/** (home) — Hero con headline + 6 cifras impacto (18.175 listings, 19.696 plazas, 18.184 HUT, 40% concentracion Sant Josep, 16,2% vacios, 6,9% esporadico) + 3 parrafos narrativos + tabla per illa + 4 story cards.
|
||||
- **/mapa** — MapLibre 100vh. Filtro por isla. Toggle de capas. Popup on-click en seccion censal con stats. Clusters Airbnb clickables (zoom expansion). Leyenda dual.
|
||||
- **/metodologia** — 5 fuentes con links, seccion "Por que dos escalas al mapa", 4 limitaciones, tabla de fechas de snapshot, licencia CC BY-SA 4.0.
|
||||
|
||||
## Lo que hay que hacer (Fase 3)
|
||||
|
||||
Segun `FASE-3-lanzamiento.md`, las tareas originales son:
|
||||
|
||||
1. Pagina `/illes` comparativa entre islas (4 cards: Mallorca, Menorca, Eivissa, Formentera con datos especificos de cada una)
|
||||
2. Pagina `/dades` descarga de CSVs/parquet
|
||||
3. Pagina `/premsa` kit de prensa
|
||||
4. SEO basico (sitemap, robots.txt, meta description, OG image)
|
||||
5. Open Graph cards (imagen de 1200x630 para previsualizaciones)
|
||||
6. Outreach a prensa local
|
||||
7. Deploy a Vercel con dominio definitivo
|
||||
8. Configurar analytics (opcional)
|
||||
|
||||
**Decision pendiente con el usuario**: nombre del proyecto en Vercel (`casestancades.vercel.app`?) y dominio definitivo (`.cat`, `.org`, `.es`?).
|
||||
|
||||
## Headlines y stats a destacar en el home
|
||||
|
||||
(Ya implementados en `/` y `/mapa` en Fase 2)
|
||||
|
||||
- **18.175 listings activos** en Airbnb Mallorca+Menorca, con **105.738 plazas** (`accommodates`)
|
||||
- **18.184 plazas legales** declaradas en HUT Eivissa — **40%** concentradas en Sant Josep (7.296) mientras Eivissa capital solo tiene **236** (41 registros)
|
||||
- **95.4%** de los listings activos son `Entire home/apt` (pisos completos)
|
||||
- **98.8%** tiene `license` rellenado en Airbnb — pero el Govern no valida ese campo
|
||||
- **$258M** de ingresos estimados Airbnb L365d en Mallorca+Menorca
|
||||
- INE CCAA: **16.2%** de viviendas vacias + **6.9%** de uso esporadico
|
||||
|
||||
**Insight narrativo central**:
|
||||
> En Eivissa hay 41 registros HUT legales en la ciudad (50.000 hab.) y 945 en Sant Josep. Donde estan las 7.000+ plazas que oferta Airbnb en Eivissa? El gap entre el dato legal y el rascado ES la denuncia.
|
||||
|
||||
## Traps y gotchas (no perder tiempo)
|
||||
|
||||
1. **Bug pre-existente en `dataset_web.json`**: arreglado en `scripts/04_regenerate_web_json.py`. NO usar el output directo de `02_build_dataset.py` (multiplica valores de Eivissa/Formentera por n secciones).
|
||||
2. **Typo persistente**: el XLSX del INE se llama `viviendas vacias-hiopotecas.xlsx` (con "h-i-o"). Si alguien lo "arregla", el script 01 falla.
|
||||
3. **Dataset hybrid**: la columna `granularidad` indica si la feature es `seccion_censal` o `municipio`. NO mezclar al pintar — Eivissa/Formentera tienen un solo valor por municipio replicado a todas las secciones.
|
||||
4. **Vivienda INE solo CCAA**: los `*_pct_ccaa` son constantes para TODAS las features. Documentar en /metodologia y en el popup del mapa.
|
||||
5. **No scrappear**: nunca Idealista, nunca Airbnb directo. Solo datos abiertos.
|
||||
6. **No build sin pedir**: el usuario es dev pero odia perder tiempo en builds innecesarios. Iterar con `pnpm dev` y solo build cuando pida.
|
||||
7. **Conventional commits**: usar `feat(web):`, `fix(map):`, etc. NUNCA anadir "Co-Authored-By" ni atribucion a IA.
|
||||
8. **Encoding**: los archivos raw ya estan normalizados a UTF-8.
|
||||
9. **macOS case-insensitive**: la carpeta se creo como `VIvienda` pero el filesystem la resuelve como `Vivienda`. No es bug.
|
||||
10. **Node 22 + pnpm 11 obligatorio** (NO Node 20). El HANDOFF original decia Node 20 pero Astro 7 requiere Node 22+. Decidido en sesion de Fase 2.
|
||||
11. **TypeScript 5.x** (NO 7.x) por incompatibilidad con `@astrojs/check`.
|
||||
12. **`prerender = false` en cada pagina** para que el i18n funcione. Sin esto, el cookie no se lee en dev/build.
|
||||
|
||||
## Preferencias del usuario (descubiertas en sesiones anteriores)
|
||||
|
||||
- Idioma del proyecto: **catalan principal** + castellano. El usuario escribe en espanol.
|
||||
- Estilo: **documentacion modular** (`PLAN.md` + 1 .md por fase), iteracion paso a paso.
|
||||
- Verificar claims antes de decir "si": el usuario detecta acuerdo facil y lo penaliza. Si no estas seguro, **di "dejame verificar"** y comprueba.
|
||||
- Respetar la regla "no build": no compilar/ejecutar proyectos sin pedir.
|
||||
- NO asumir respuestas: si hay duda, **preguntar con `question` tool**.
|
||||
- **Honestidad radical sobre limitaciones**: si una fuente es CCAA, decirlo en /metodologia y en el popup del mapa.
|
||||
|
||||
## Datos cuantitativos de la conferencia OHIB (12-13 nov 2025)
|
||||
|
||||
Guardados en `docs/conferencia-OHIB-2025/` (15 JPGs + Info.pdf, ignorados en git). Datos clave para usar en el storytelling:
|
||||
|
||||
- Compraventa 2024 €/m²: Formentera 7.353 / Ibiza 4.331 / Mallorca 3.500 / Menorca 2.748 / Balears media 3.609
|
||||
- CEE parque residencial Balears: 1,1% A, 2,2% B, 3,7% C, 9,5% D, 43,9% E, 12,5% F, 27,0% G → **83,4% en E/F/G**
|
||||
- 34,79% unifamiliares vs 1,16% plurifamiliares
|
||||
- Fuentes oficiales mapeadas: INE, Catastro, MIVAU, MTERD, DGHA, IBAVI, ATIB, IBESTAT, ICGIB
|
||||
|
||||
Frase literal del usuario que define el proyecto:
|
||||
> "el problema no son los legales, son los que no son legales. En Ibiza, ninguna vivienda en plurifamiliar puede alquilarse y hay miles de anuncios."
|
||||
|
||||
## Preguntas abiertas (preguntar al usuario en la nueva sesion)
|
||||
|
||||
1. **¿Vercel ya configurado / nombre del proyecto?** Recomendacion: `casestancades.vercel.app` (libre presumiblemente). Login con GitHub, free tier.
|
||||
2. **¿Dominio `.cat` o `.org` para lanzamiento?** El usuario dijo "de momento el dominio no es importante" pero para outreach a prensa conviene uno definitivo.
|
||||
3. **¿Open Graph image estatica o dinamica?** Estatica: 1 imagen fija. Dinamica: HTML+canvas que genera una imagen con la headline y las cifras (mas viralizable).
|
||||
4. **¿Outreach a prensa local ahora o despues del lanzamiento?** Recomiendo despues: tener URL definitiva + URL de /premsa + OG images listas.
|
||||
5. **¿Analytics?** Posibilidad: Plausible (privacy-friendly, sin cookies) o ninguno. Para una web de denuncia, menos tracking = mejor.
|
||||
6. **¿Nombre de la organizacion/portavoz?** Para la pagina /premsa y para la nota de contacto en /metodologia. Si no tiene, dejar como "iniciativa ciudadana" o "colectivo X".
|
||||
|
||||
## Estructura de archivos esperada al cerrar Fase 3
|
||||
|
||||
```
|
||||
web/src/pages/
|
||||
├── index.astro # home
|
||||
├── mapa.astro # mapa interactivo
|
||||
├── metodologia.astro # fuentes y limitaciones
|
||||
├── illes.astro # comparativa por isla (NUEVO)
|
||||
├── dades.astro # descarga de datasets (NUEVO)
|
||||
└── premsa.astro # kit de prensa (NUEVO)
|
||||
|
||||
web/public/
|
||||
├── og-image.png # 1200x630 Open Graph (NUEVO)
|
||||
├── press/ # kit de prensa descargable (NUEVO)
|
||||
└── (resto igual)
|
||||
|
||||
web/src/content/ # opcional: blog/notas
|
||||
```
|
||||
|
||||
## Convenciones de commits
|
||||
|
||||
```
|
||||
feat(web): ...
|
||||
fix(map): ...
|
||||
chore(web): ...
|
||||
docs(plan): ...
|
||||
```
|
||||
|
||||
Tags al cerrar fase: `fase-3-completa`.
|
||||
|
||||
## Que NO hacer
|
||||
|
||||
- No scrappear Idealista o Airbnb.
|
||||
- No usar Leaflet (usar MapLibre GL).
|
||||
- No usar TileMill/MBTiles (usar tippecanoe → pmtiles).
|
||||
- No meter viviendas vacias a nivel CCAA fingiendo que son seccion censal.
|
||||
- No anadir "Co-Authored-By" ni atribucion a IA en commits.
|
||||
- No commitear archivos raw grandes (ya en `.gitignore`).
|
||||
- No asumir respuestas: si hay duda, **preguntar con `question` tool**.
|
||||
|
||||
## TL;DR
|
||||
|
||||
Fase 3 = 3 paginas nuevas (illes, dades, premsa) + SEO + OG + Vercel + outreach. La web MVP ya funciona en local. Las decisiones tecnicas estan todas tomadas en Fase 2. Solo queda ejecutar outreach, contenido editorial y deploy.
|
||||
@@ -1,62 +0,0 @@
|
||||
# Plan: Cases Buides / Tancades (Vivienda vacía + alquiler temporal en Balears)
|
||||
|
||||
## 1. Resumen ejecutivo
|
||||
|
||||
Web publica que cruza dos datos oficiales - INE (consumo electrico por seccion censal, como proxy de vivienda semi-vacia) + Inside Airbnb (listings georreferenciados) - para visibilizar la presion turistica sobre el parque residencial de Balears. Audiencia principal: ciudadania general ibicenca. Plazo objetivo: MVP publico en 4-6 semanas. Stack: Python (pipeline de datos) + Astro (web estatica) + MapLibre GL (mapas interactivos) + Vercel (hosting).
|
||||
|
||||
## 2. Decisiones cerradas
|
||||
|
||||
| Decision | Valor | Razon |
|
||||
|---|---|---|
|
||||
| Formato entregable | Web publica | Compartible, viralizable, accesible para prensa y ciudadania |
|
||||
| Audiencia | Ciudadania general ibicenca | Lenguaje accesible, storytelling visual, foco local |
|
||||
| Granularidad datos | Seccion censal (500-2.000 hogares) | INE solo llega a este nivel, defendible y honesto |
|
||||
| Plazo total | 4-6 semanas (MVP) | Validar rapido, iterar despues |
|
||||
| Datos vivienda vacia | Consumo electrico INE (ya disponible) | Unico dato publico oficial con cobertura islenya completa |
|
||||
| Datos alquiler temporal | Inside Airbnb (datos abiertos) | Legal, reproducible, suficiente para cota inferior |
|
||||
| Alcance geografico | Balears entero (4 islas) | Comparativa potente entre islas, reutiliza trabajo |
|
||||
| Recursos | Solo, perfil tecnico dev | Plan realista sin dependencias externas |
|
||||
| Estilo iteracion | Waterfall secuencial (4 fases) | Mantener foco, evitar scope creep |
|
||||
| Documentacion | PLAN.md + 1 doc por fase | Modular, facil de iterar, auditable |
|
||||
|
||||
## 3. Fases (resumen)
|
||||
|
||||
- **Fase 0 (sem 1) - Setup.** Repo git, entorno Python/Node, descarga de shapefile de secciones censales Balears (INE) e Inside Airbnb listings para las 4 islas, mover XLSXs del usuario a `data/raw/`.
|
||||
- **Fase 1 (sem 2) - Datos.** Pipeline Python: limpiar XLSX INE -> cargar shapefile -> cargar listings -> spatial join listings->seccion censal -> agregar dataset -> generar `dataset.parquet` y `tiles.pmtiles`.
|
||||
- **Fase 2 (sem 3-4) - Web MVP.** Astro + MapLibre GL: home con headline + `/mapa` interactivo (capa semi-vacias + capa Airbnb) + `/metodologia`. Despliegue en Vercel con URL temporal.
|
||||
- **Fase 3 (sem 5-6) - Lanzamiento.** `/illes` comparativa entre islas + `/dades` descarga de CSVs/parquet + `/premsa` kit de prensa + SEO basico + Open Graph cards + outreach a prensa local.
|
||||
|
||||
## 4. Riesgos
|
||||
|
||||
| Riesgo | Mitigacion |
|
||||
|---|---|
|
||||
| Inside Airbnb no se actualiza con frecuencia | Snapshot con fecha visible en `/metodologia`; documentar fuente alternativa (registro HUT del Govern) para v2 |
|
||||
| Sesgo: no todos los listings estan en Airbnb | Comunicar en metodologia: es **cota inferior** de la presion turistica real |
|
||||
| Granularidad seccion censal (no direccion exacta) | Reenmarcar narrativamente: "mapa por barrio de 500-2.000 hogares" en vez de portal exacto. Honesto y defendible. |
|
||||
| Scraping / TOS de portales | NO scrappear Idealista/Airbnb directamente; usar solo datos abiertos (Inside Airbnb + INE/Catastro) |
|
||||
| Dominio `.cat` ocupado o caro | Plan B: `.es`, `.org`, subdominio Vercel (`casestancades.vercel.app`) |
|
||||
| Demanda legal por denuncia publica | Disclaimer "datos publicos, metodologia abierta, sin acusacion individual" en pie de pagina |
|
||||
| Shapefile secciones censales no incluye Formentera como tal | Validar en Fase 0; si falta, trabajar con secciones censales de los 4 municipios de Eivissa + Formentera juntos |
|
||||
|
||||
## 5. Estado actual
|
||||
|
||||
- [x] Carpeta `/Users/ichi/Desktop/DEV/VIvienda/` identificada con datos del usuario
|
||||
- [x] XLSXs INE descargados por el usuario (`viviendas vacias-hipotecas.xlsx`, `39365(1).xlsx`)
|
||||
- [x] Capturas de conferencia OHIB (12-13 nov 2025) revisadas
|
||||
- [x] Plan inicial creado y validado con el usuario
|
||||
- [x] `PLAN.md` escrito
|
||||
- [x] `FASE-0-setup.md` escrito (cerrado)
|
||||
- [x] Fase 0 ejecutada: entorno, shapefile, listings Mallorca+Menorca, HUT Eivissa, IBESTAT Formentera
|
||||
- [x] Insight clave: legal != realidad. Mallorca/Menorca capturan Airbnb (real), Eivissa/Formentera solo legal. La diferencia ES la denuncia.
|
||||
- [x] Fase 1 ejecutada: scripts 01/02/03 reproducibles, dataset.parquet + tiles.pmtiles generados, STATS.md con 18.175 listings Airbnb y 18.184 plazas HUT
|
||||
- [x] Fase 2 ejecutada: web Astro + MapLibre con 3 paginas (home, mapa, metodologia), i18n CA/ES con cookie, choropleth mixto por isla, clusters Airbnb
|
||||
- [ ] Fase 3 ejecutada
|
||||
- [ ] Web publica desplegada en dominio definitivo
|
||||
|
||||
## 6. Notas de iteracion
|
||||
|
||||
_Espacio para cambios futuros. Cada vez que se ajuste el plan, dejar nota con fecha y razon._
|
||||
|
||||
- **2026-07-13** - Plan inicial creado tras revision de datos del usuario y conferencia OHIB. Decisiones cerradas: web publica, ciudadania ibicenca, seccion censal, 4-6 semanas, Inside Airbnb, Balears entero, dev solo, waterfall, documentacion modular.
|
||||
- **2026-07-14** - Fase 1 completada. Outputs: `data/output/dataset.parquet` (41KB), `dataset_web.json` (1KB), `tiles.pmtiles` (1.5MB), `STATS.md`. Limitacion documentada: vivienda INE solo a nivel CCAA (no seccion censal). Insight añadido: Sant Josep de sa Talaia (Eivissa) tiene 945 HUT/7.296 plazas vs Eivissa capital 41/236.
|
||||
- **2026-07-14** - Fase 2 completada. Web `web/` con Astro 7 + MapLibre 5 + PMTiles 4 + Tailwind 4. 3 paginas (home, mapa, metodologia) + i18n CA/ES con cookie. Choropleth mixto: `airbnb_listings` (Mallorca/Menorca) + `hut_plazas` (Eivissa/Formentera). Clusters Airbnb con 18.391 puntos. Bug pre-existente en `dataset_web.json` arreglado en `scripts/04_regenerate_web_json.py` (suma por seccion multiplicaba valores de Eivissa/Formentera). Tag `fase-2-completa`.
|
||||
Binary file not shown.
@@ -1,59 +0,0 @@
|
||||
# Origen de las dades en `data/raw/`
|
||||
|
||||
## Archivos INE (proporcionados por el usuario)
|
||||
|
||||
### `viviendas vacias-hipotecas.xlsx`
|
||||
|
||||
- **Origen**: Instituto Nacional de Estadistica (INE). Tabla derivada del "Censo de poblacion y viviendas" + datos de consumo electrico.
|
||||
- **URL de descarga**: https://www.ine.es (tabla 39365 + tabla especifica d'intensitat d'us)
|
||||
- **Fecha de descarga**: 2025 (proporcionado por el usuario del proyecto)
|
||||
- **Descripcion**: 6 fulles. La full 1 conte dades d'intensitat d'us de les vivendes segons consum electric per seccio censal. Inclou Total Nacional + Illes Balears (provincies + seccions).
|
||||
- **Tamano**: 35 KB
|
||||
|
||||
### `39365(1).xlsx`
|
||||
|
||||
- **Origen**: Instituto Nacional de Estadistica (INE). Tabla 39365 - "Viviendas turisticas en Espana".
|
||||
- **URL de descarga**: https://www.ine.es/jaxiT3/Tabla.htm?t=39365
|
||||
- **Fecha de descarga**: 2025 (proporcionado por el usuario del proyecto)
|
||||
- **Descripcion**: 1 full. Serie temporal 2020M08 - 2025M05. Percentage de vivendes turistiques sobre el total per comunitat autonoma.
|
||||
- **Tamano**: 10 KB
|
||||
|
||||
## Shapefile de secciones censales de Balears
|
||||
|
||||
- **Origen**: Instituto Nacional de Estadistica (INE). Cartografia censal.
|
||||
- **URL de descarga**: https://www.ine.es/prodyser/cartografia/seccionado_2025.zip
|
||||
- **Fecha de descarga**: 14 julio 2026 (descargado por el asistente)
|
||||
- **Descripcion**: Poligons de les seccions censals per a les Illes Balears.
|
||||
- **CRS original**: ETRS89 (EPSG:25830), reprojectat a WGS84 (EPSG:4326) per a la web.
|
||||
- **Tamano ZIP**: 60 MB (todo Espana), GPKG Balearic Islands: 5.3 MB
|
||||
|
||||
## Inside Airbnb listings
|
||||
|
||||
- **Origen**: Inside Airbnb (proyecto independiente que scrapea Airbnb y publica datos abiertos).
|
||||
- **URL de descarga**: http://insideairbnb.com/get-the-data/
|
||||
- **Archivos descargados**:
|
||||
- Mallorca: `https://data.insideairbnb.com/spain/islas-baleares/mallorca/2026-06-23/data/listings.csv.gz` (10 MB)
|
||||
- Menorca: `https://data.insideairbnb.com/spain/islas-baleares/menorca/2026-06-30/data/listings.csv.gz` (2.3 MB)
|
||||
- **Fecha**: snapshot 2026-06
|
||||
- **Licencia**: Creative Commons (consultar web del proyecto)
|
||||
- **Limitacion**: NO hay datos para Eivissa ni Formentera
|
||||
|
||||
## Registro oficial HUT de Eivissa (proporcionado por el usuario)
|
||||
|
||||
- **Origen**: Govern de les Illes Balears - Conselleria de Turisme. Registro oficial de Habitatges d'Us Turistic.
|
||||
- **URL del portal**: https://www.caib.es (buscador publico, no descarga directa)
|
||||
- **Archivo recibido**: `List-habitatges-turistics_-14072026.xls` (HTML con extension .xls, encoding ISO-8859-1)
|
||||
- **Fecha**: 14 julio 2026
|
||||
- **Tamano**: 4.2 MB original, 568 KB CSV limpio
|
||||
- **Coverage**: SOLO accommodations legales registradas
|
||||
- **Insight**: el problema real son los ilegales (no capturados aqui)
|
||||
|
||||
## IBESTAT Formentera 2019 (proporcionado por el usuario)
|
||||
|
||||
- **Origen**: IBESTAT (Institut d'Estadistica de les Illes Balears). Indicador 208.34208023 - "Establiments turistics de Formentera".
|
||||
- **URL del portal**: https://ibestat.caib.es/ (indicador 208.34208023)
|
||||
- **Archivo recibido**: `IBESTAT_indicador_208_34208023_Establiments_turístics_2019.xls` (OLE binary .xls)
|
||||
- **Ano de referencia**: 2019 (no se encontro nada mas reciente)
|
||||
- **Tamano**: 38.5 KB original, 2 KB JSON limpio
|
||||
- **Coverage**: Datos agregados de Formentera (no por municipio, no por direccion)
|
||||
- **Limitacion**: Solo establishments legales (oficial)
|
||||
@@ -1,122 +0,0 @@
|
||||
# VALIDACION de los datos en `data/raw/`
|
||||
|
||||
Resultado de la validacion de los archivos descargados. Ejecutado en setup de Fase 0.
|
||||
|
||||
## Datos INE (proporcionados por el usuario)
|
||||
|
||||
### `viviendas vacias-hipotecas.xlsx`
|
||||
|
||||
- Tamano: 34.2 KB
|
||||
- 6 sheets
|
||||
- **Sheet util: `tabla-59531`** (Viviendas por intensidad de uso a partir del consumo electrico)
|
||||
- Los otros 5 sheets son datos de hipotecas (NO se usan en este proyecto)
|
||||
- Encoding: UTF-8 (con cabecera en espanol)
|
||||
|
||||
### `39365(1).xlsx`
|
||||
|
||||
- Tamano: 10.0 KB
|
||||
- 1 sheet util: `tabla-39365` (Viviendas turisticas en Espana, % sobre total, serie 2020M08-2025M05)
|
||||
|
||||
## Shapefile INE 2025
|
||||
|
||||
- **Origen**: Instituto Nacional de Estadistica (INE). Cartografia censal 2025.
|
||||
- **URL**: https://www.ine.es/prodyser/cartografia/seccionado_2025.zip
|
||||
- **Tamano ZIP**: 57.5 MB (todo Espana, 36.554 features)
|
||||
- **CRS original**: EPSG:25830 (ETRS89 Huso 30 Norte)
|
||||
- **Tamano GeoPackage Balearic Islands**: 5.3 MB
|
||||
- **CRS final**: EPSG:4326 (WGS84, listo para web)
|
||||
- **Features en Illes Balears**: 674 secciones censales
|
||||
- **Municipios en Illes Balears**: 67
|
||||
- **Columnas**: CUSEC, CUMUN, CSEC, CDIS, CMUN, CPRO, CCA, CUDIS, CLAU2, NPRO, NCA, CNUT0/1/2/3, NMUN, geometry
|
||||
- **Codigos clave**:
|
||||
- CPRO = '07' para Balears
|
||||
- CCA = '04' para Illes Balears
|
||||
- CUSEC = CPRO(2) + CMUN(3) + CDIS(2) + CSEC(3), total 10 digitos
|
||||
|
||||
## Datos de alquiler turistico / temporal
|
||||
|
||||
### Inside Airbnb listings (Mallorca + Menorca)
|
||||
|
||||
- **Origen**: Inside Airbnb (datos abiertos scrapeados de Airbnb)
|
||||
- **URLs**:
|
||||
- Mallorca: `https://data.insideairbnb.com/spain/islas-baleares/mallorca/2026-06-23/data/listings.csv.gz` (10.0 MB, 45.741 listings)
|
||||
- Menorca: `https://data.insideairbnb.com/spain/islas-baleares/menorca/2026-06-30/data/listings.csv.gz` (2.3 MB, 8.492 listings)
|
||||
- **Columnas clave**: id, latitude, longitude, room_type, property_type, price, availability_365, minimum_nights, neighbourhood, host_id
|
||||
- **90 columnas** en total (snapshot completo)
|
||||
- **Coverage**: Airbnb listings (incluye legales E ILEGALES - cota inferior de la presion real)
|
||||
- **Limitacion**: NO hay datos para Eivissa ni Formentera
|
||||
|
||||
### Registro oficial HUT de Eivissa (proporcionado por el usuario)
|
||||
|
||||
- **Origen**: Govern de les Illes Balears - Conselleria de Turisme
|
||||
- **Archivo original**: `List-habitatges-turistics_-14072026.xls` (HTML con extension .xls, encoding ISO-8859-1)
|
||||
- **CSV limpio**: `hut_eivissa_2026-07-14.csv` (568 KB)
|
||||
- **Snapshot**: 14 de julio de 2026
|
||||
- **2.369 registros** totales (5 municipios + 5 anomalias "NUEVO BOLSA DE PLAZAS")
|
||||
- **18.184 plazas/camas** totales
|
||||
- **Distribucion por municipio**:
|
||||
- SANT JOSEP DE SA TALAIA: 945
|
||||
- SANTA EULARIA DES RIU: 803
|
||||
- SANT ANTONI DE PORTMANY: 330
|
||||
- SANT JOAN DE LABRITJA: 245
|
||||
- EIVISSA: 41
|
||||
- NUEVO BOLSA DE PLAZAS: 5 (anomalias, excluir)
|
||||
- **Columnas clave**:
|
||||
- Numero Inscripcio (numero de registro oficial)
|
||||
- Referencia cadastral (20 caracteres, geocodificable a parcela)
|
||||
- Direccion (texto)
|
||||
- Municipi (municipio)
|
||||
- Total Places (plazas/camas)
|
||||
- Sub-tipus (Estancia/Vivienda Turistica Vacacional)
|
||||
- **Coverage**: SOLO accommodations legales registradas
|
||||
- **Insight del usuario**: "el problema no son los legales, son los que no son legales. En Ibiza, ninguna vivienda en plurifamiliar puede alquilarse y hay miles de anuncios". Por tanto, el HUT es una COTA INFERIOR muy conservadora.
|
||||
|
||||
### IBESTAT Formentera 2019 (proporcionado por el usuario)
|
||||
|
||||
- **Origen**: IBESTAT (Institut d'Estadistica de les Illes Balears) - indicador 208.34208023
|
||||
- **Archivo original**: `IBESTAT_indicador_208_34208023_Establiments_turístics_2019.xls` (38.5 KB, OLE binary .xls)
|
||||
- **JSON limpio**: `ibestat_formentera_2019.json` (2 KB)
|
||||
- **Snapshot**: ano 2019 (datos antiguos, no se encontro nada mas reciente)
|
||||
- **Datos**: Tabla agregada con tipologia, unidades y plazas para Formentera como una unidad
|
||||
- **1.375 unidades totales, 14.935 plazas totales**
|
||||
- **Desglose**:
|
||||
- HABITATGES TURISTICS DE VACANCES (HTV): 168 unidades, 1.927 plazas
|
||||
- ESTADES TURISTIQUES: 1.086 unidades, 4.912 plazas
|
||||
- Hotels (1-5*): 19 unidades, 3.008 plazas
|
||||
- Apartments: 73 unidades, 2.758 plazas
|
||||
- Otros: resto
|
||||
- **Coverage**: SOLO establishments legales (datos oficiales agregados)
|
||||
- **Limitacion**: No incluye datos a nivel de parcela/direccion. Datos agregados solo a nivel isla.
|
||||
|
||||
## Resumen de cobertura
|
||||
|
||||
| Isla | Shapefile | Listings (todos) | Legal (HUT) | Plazas legales | Calidad |
|
||||
|---|---|---|---|---|---|
|
||||
| Mallorca | OK (674 secc.) | OK (45.741 Airbnb) | n.d. | n.d. | Buena (Airbnb) |
|
||||
| Menorca | OK (674 secc.) | OK (8.492 Airbnb) | n.d. | n.d. | Buena (Airbnb) |
|
||||
| Eivissa | OK (674 secc.) | NO en Airbnb | OK (2.369 HUT 2026) | 18.184 | Cota inferior (HUT) |
|
||||
| Formentera | OK (674 secc.) | NO en Airbnb | OK (1.375 estab. 2019) | 14.935 | Cota inferior (agregado) |
|
||||
|
||||
**Total listings Airbnb disponibles**: 54.233 (Mallorca + Menorca)
|
||||
**Total establishments legales documentados**: 3.744 (Eivissa 2.369 + Formentera 1.375)
|
||||
**Total plazas legales documentadas**: 33.119 (Eivissa 18.184 + Formentera 14.935)
|
||||
|
||||
## Implicaciones para el proyecto
|
||||
|
||||
- **Cobertura geografica**: 4/4 islas, pero con calidad desigual
|
||||
- **Cobertura de realidad**: Mallorca+Menorca capturan Airbnb (cota inferior de presion real). Eivissa+Formentera solo capturan legal (cota inferior de legal). La realidad (legal+ilegal) es desconocida para Eivissa/Formentera
|
||||
- **Mensaje narrativo**: la diferencia entre Airbnb y HUT es la denuncia. "El Govern reconoce X plazas legales en Eivissa, pero en Mallorca donde tenemos el dato completo, las plazas reales son Y veces mas"
|
||||
- **Falta**: scraping o fuente complementaria para Eivissa/Formentera que capture listings ilegales (no en v0)
|
||||
|
||||
## Resumen de espacio en disco
|
||||
|
||||
- Carpeta `data/raw/`: ~79 MB total
|
||||
- XLSXs INE: 45 KB
|
||||
- Shapefile ZIP: 60 MB
|
||||
- GeoPackage Balears: 5.3 MB
|
||||
- Listings Airbnb Mallorca+Menorca: 12.3 MB
|
||||
- HUT Eivissa HTML fuente: 4.2 MB
|
||||
- HUT Eivissa CSV limpio: 568 KB
|
||||
- IBESTAT Formentera JSON: 2 KB
|
||||
- Carpeta `docs/conferencia-OHIB-2025/`: ~50 MB (15 JPGs + PDF)
|
||||
- Total proyecto local: ~130 MB
|
||||
@@ -1,106 +0,0 @@
|
||||
{
|
||||
"metadata": {
|
||||
"sector": "208 Turisme",
|
||||
"num_actividad": "34 208 023",
|
||||
"denominacion": "Establiments turístics de Formentera",
|
||||
"tabla": "1. Allotjaments turístics per grup, modalitat i categoria",
|
||||
"unidad": "Tipologia d'establiment, núm. d'unitats d'allotjament",
|
||||
"periodo": 2019,
|
||||
"ultima_actualizacion": "2019-12-01",
|
||||
"fuente": "Consell Insular de Formentera. Àrea de Promoció",
|
||||
"total_unidades": 1375,
|
||||
"total_plazas": 14935
|
||||
},
|
||||
"data": [
|
||||
{
|
||||
"tipologia": "APARTAMENTS 1 CLAU",
|
||||
"unidades": 56,
|
||||
"plazas": 1758
|
||||
},
|
||||
{
|
||||
"tipologia": "APARTAMENTS 2 CLAUS",
|
||||
"unidades": 10,
|
||||
"plazas": 641
|
||||
},
|
||||
{
|
||||
"tipologia": "APARTAMENTS 3 CLAUS",
|
||||
"unidades": 5,
|
||||
"plazas": 201
|
||||
},
|
||||
{
|
||||
"tipologia": "APARTAMENTS 4 CLAUS",
|
||||
"unidades": 2,
|
||||
"plazas": 158
|
||||
},
|
||||
{
|
||||
"tipologia": "AGROTURISME",
|
||||
"unidades": 1,
|
||||
"plazas": 12
|
||||
},
|
||||
{
|
||||
"tipologia": "CASA D'HOSTES",
|
||||
"unidades": 8,
|
||||
"plazas": 125
|
||||
},
|
||||
{
|
||||
"tipologia": "CIUTAT DE VACANCES",
|
||||
"unidades": 2,
|
||||
"plazas": 1193
|
||||
},
|
||||
{
|
||||
"tipologia": "FONDA",
|
||||
"unidades": 1,
|
||||
"plazas": 30
|
||||
},
|
||||
{
|
||||
"tipologia": "HOSTAL 1 *",
|
||||
"unidades": 10,
|
||||
"plazas": 508
|
||||
},
|
||||
{
|
||||
"tipologia": "HOSTAL 2*",
|
||||
"unidades": 5,
|
||||
"plazas": 292
|
||||
},
|
||||
{
|
||||
"tipologia": "HOSTAL 3*",
|
||||
"unidades": 2,
|
||||
"plazas": 170
|
||||
},
|
||||
{
|
||||
"tipologia": "HOTEL 1*",
|
||||
"unidades": 3,
|
||||
"plazas": 304
|
||||
},
|
||||
{
|
||||
"tipologia": "HOTEL 2*",
|
||||
"unidades": 5,
|
||||
"plazas": 347
|
||||
},
|
||||
{
|
||||
"tipologia": "HOTEL 3*",
|
||||
"unidades": 4,
|
||||
"plazas": 380
|
||||
},
|
||||
{
|
||||
"tipologia": "HOTEL 4*",
|
||||
"unidades": 6,
|
||||
"plazas": 1819
|
||||
},
|
||||
{
|
||||
"tipologia": "HOTEL 5*",
|
||||
"unidades": 1,
|
||||
"plazas": 158
|
||||
},
|
||||
{
|
||||
"tipologia": "HABITATGES TURÍSTICS DE VACANCES",
|
||||
"unidades": 168,
|
||||
"plazas": 1927
|
||||
},
|
||||
{
|
||||
"tipologia": "ESTADES TURÍSTIQUES",
|
||||
"unidades": 1086,
|
||||
"plazas": 4912
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user