chore: estructura inicial del proyecto
This commit is contained in:
+66
@@ -0,0 +1,66 @@
|
||||
# Datos crudos (no commitear por tamaño)
|
||||
data/raw/*.xlsx
|
||||
data/raw/*.csv
|
||||
data/raw/*.csv.gz
|
||||
data/raw/*.zip
|
||||
data/raw/*.shp
|
||||
data/raw/*.shx
|
||||
data/raw/*.dbf
|
||||
data/raw/*.prj
|
||||
data/raw/*.cpg
|
||||
data/raw/*.sbn
|
||||
data/raw/*.sbx
|
||||
data/raw/*.fbn
|
||||
data/raw/*.fbx
|
||||
data/raw/*.ain
|
||||
data/raw/*.aih
|
||||
data/raw/*.atx
|
||||
data/raw/*.ixs
|
||||
data/raw/*.mxs
|
||||
data/raw/*.qix
|
||||
data/raw/*.qpj
|
||||
data/raw/*.xml
|
||||
|
||||
# Capturas de la conferencia (grandes, locales unicamente)
|
||||
docs/**/*.jpg
|
||||
docs/**/*.JPG
|
||||
docs/**/*.jpeg
|
||||
docs/**/*.png
|
||||
|
||||
# Procesado (regenerable desde raw con scripts/)
|
||||
data/processed/
|
||||
data/output/
|
||||
|
||||
# Node
|
||||
node_modules/
|
||||
.pnpm-store/
|
||||
dist/
|
||||
.astro/
|
||||
.vercel/
|
||||
*.log
|
||||
|
||||
# Python
|
||||
.venv/
|
||||
venv/
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*.egg-info/
|
||||
.pytest_cache/
|
||||
.mypy_cache/
|
||||
.ruff_cache/
|
||||
|
||||
# Entorno
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# macOS
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
# 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
|
||||
- [ ] 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
|
||||
- [ ] `git init` en `/Users/ichi/Desktop/DEV/VIvienda/`
|
||||
- [ ] 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`
|
||||
- [ ] Hacer commit inicial con estructura + `.gitignore` + este PLAN
|
||||
- [ ] (Opcional) crear repo en GitHub y vincular
|
||||
|
||||
### Reorganizacion de archivos existentes
|
||||
- [ ] Mover `Info.pdf` y los 19 `.jpg` de la conferencia a `docs/conferencia-OHIB-2025/`
|
||||
- [ ] Mover `viviendas vacias-hipotecas.xlsx` y `39365(1).xlsx` a `data/raw/`
|
||||
- [ ] Documentar el origen de cada archivo en `data/raw/ORIGEN.md`
|
||||
|
||||
### Entorno Python
|
||||
- [ ] Instalar `uv` (gestor de entornos y paquetes rapido)
|
||||
- [ ] `uv venv .venv` en la raiz del proyecto
|
||||
- [ ] Crear `requirements.txt` con: pandas, openpyxl, geopandas, duckdb, shapely, pyproj, fiona, pyarrow
|
||||
- [ ] `uv pip install -r requirements.txt`
|
||||
- [ ] Verificar: `python -c "import geopandas, duckdb; print('OK')"`
|
||||
|
||||
### Entorno Node
|
||||
- [ ] Instalar Node 20+ (con `nvm` o `brew`)
|
||||
- [ ] Instalar pnpm (`npm install -g pnpm`)
|
||||
|
||||
### Descarga de datos externos
|
||||
- [ ] Descargar **shapefile de secciones censales de Balears** desde INE
|
||||
- Fuente: https://www.ine.es/prodyser/cartografia/seccionado_2025/
|
||||
- Descargar las 4 provincias: Mallorca (07), Menorca (07), Eivissa (07), Formentera (07)
|
||||
- Verificar que incluye geometria poligonal
|
||||
- [ ] Descargar **Inside Airbnb listings** para las 4 islas
|
||||
- Fuente: http://insideairbnb.com/get-the-data/
|
||||
- Snapshot mas reciente disponible para: Mallorca, Menorca, Eivissa, Formentera
|
||||
- Formato: `listings.csv.gz` (revisar tamano y fecha)
|
||||
|
||||
### Validacion
|
||||
- [ ] Shapefile abre con geopandas, tiene CRS correcto, conteo de features > 0
|
||||
- [ ] Listings CSV abre con pandas, columnas esperadas presentes
|
||||
- [ ] XLSXs del usuario abren con openpyxl/pandas
|
||||
- [ ] Anotar numero de filas de cada dataset en `data/raw/VALIDACION.md`
|
||||
|
||||
### Cierre
|
||||
- [ ] Commit final con tag `fase-0-completa`
|
||||
- [ ] Actualizar PLAN.md: marcar Fase 0 como completada
|
||||
- [ ] 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._
|
||||
|
||||
## Problemas encontrados
|
||||
|
||||
_Llenar durante la ejecucion. Ejemplos:_
|
||||
- _El shapefile de Formentera viene en un ZIP separado y CRS distinto al de Mallorca._
|
||||
- _Inside Airbnb no tiene snapshot para Formentera separado; el de Eivissa incluye ambos._
|
||||
|
||||
## 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`.
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
# FASE 1 - Datos (semana 2)
|
||||
|
||||
## Objetivo
|
||||
|
||||
Producir el dataset final agregado por seccion censal con dos variables clave: (a) % de viviendas semi-vacias estimado por consumo electrico, y (b) numero/densidad de listings de Airbnb. Generar archivos listos para la web: `dataset.parquet` (tabla) y `tiles.pmtiles` (visualizacion geoespacial).
|
||||
|
||||
## Tareas
|
||||
|
||||
### Exploracion y limpieza
|
||||
- [ ] Cargar `viviendas vacias-hipotecas.xlsx`, inspeccionar las 6 sheets, identificar la que tiene datos por seccion censal
|
||||
- [ ] Filtrar registros de Illes Balears (codigos INE 07xxx)
|
||||
- [ ] Normalizar columnas: codigo seccion censal, % viviendas semi-vacias, % viviendas vacias, consumo mediano kWh
|
||||
- [ ] Cargar `39365(1).xlsx` (tabla 39365 viviendas turisticas), agregar a Balears como dato contextual
|
||||
|
||||
### Carga geoespacial
|
||||
- [ ] Cargar shapefile de secciones censales Balears con geopandas
|
||||
- [ ] Reproyectar a WGS84 (EPSG:4326) si esta en ETRS89 u otro CRS
|
||||
- [ ] Inspeccionar: codigo unico de seccion censal, geometria valida, total de features
|
||||
|
||||
### Inside Airbnb
|
||||
- [ ] Cargar los 4 CSVs de listings (Mallorca, Menorca, Eivissa, Formentera)
|
||||
- [ ] Columnas clave: `id`, `latitude`, `longitude`, `room_type`, `availability_365`, `price`, `neighbourhood`
|
||||
- [ ] Filtrar listings activos: `availability_365 > 0` y/o `room_type == 'Entire home/apt'`
|
||||
- [ ] Limpiar precios (quitar `$`, `,`, convertir a float)
|
||||
|
||||
### Spatial join
|
||||
- [ ] Point-in-polygon: cada listing -> seccion censal correspondiente
|
||||
- [ ] Manejar listings fuera de poligonos (zonas rurales, agua): log + excluir
|
||||
- [ ] Resultado: DataFrame con `(seccion_censal, n_listings)` por isla
|
||||
|
||||
### Agregacion por seccion censal
|
||||
- [ ] Join: seccion_censal <- (datos INE vivienda) + (conteo Airbnb)
|
||||
- [ ] Variables finales por seccion censal:
|
||||
- `cod_seccion` (PK)
|
||||
- `municipio`, `isla`
|
||||
- `n_viviendas_total`
|
||||
- `pct_viviendas_vacias`
|
||||
- `pct_uso_esporadico`
|
||||
- `consumo_mediano_kwh`
|
||||
- `n_listings_airbnb`
|
||||
- `listings_por_100_viviendas`
|
||||
- `geometry` (poligono)
|
||||
- [ ] Guardar como `data/output/dataset.parquet` (formato columnar eficiente)
|
||||
|
||||
### Tiles para mapa web
|
||||
- [ ] Generar `data/output/tiles.pmtiles` con tippecanoe a partir del GeoPackage del dataset
|
||||
- [ ] Incluir atributos de visualizacion en los tiles (no solo geometria)
|
||||
- [ ] Generar version "minima" de tiles (zoom 0-12) para web
|
||||
|
||||
### Validacion
|
||||
- [ ] `dataset.parquet` abre con duckdb/pandas
|
||||
- [ ] `tiles.pmtiles` se sirve correctamente y se ve en MapLibre local
|
||||
- [ ] Sanity checks: nº listings total razonable (>5.000 en Mallorca, >1.000 en Eivissa), sin nulos en columnas clave
|
||||
- [ ] Documentar estadisticas descriptivas en `data/output/STATS.md`
|
||||
|
||||
### Cierre
|
||||
- [ ] Commit final con tag `fase-1-completa`
|
||||
- [ ] Actualizar PLAN.md
|
||||
- [ ] Visualizar el mapa en un Jupyter notebook rapido para validar (screenshot al menos)
|
||||
|
||||
## Comandos clave
|
||||
|
||||
```bash
|
||||
# Convertir a GeoPackage para tippecanoe
|
||||
ogr2ogr -f GPKG data/output/dataset.gpkg data/output/dataset.parquet
|
||||
|
||||
# Generar tiles
|
||||
tippecanoe -o data/output/tiles.pmtiles \
|
||||
-zg \
|
||||
--drop-densest-as-needed \
|
||||
-l cases \
|
||||
--read-parallel \
|
||||
data/output/dataset.gpkg
|
||||
|
||||
# Servir localmente para testear
|
||||
python -m http.server 8000 --directory data/output
|
||||
# Abrir http://localhost:8000 en navegador con MapLibre
|
||||
|
||||
# Validar parquet con duckdb
|
||||
python -c "import duckdb; print(duckdb.query('SELECT isla, COUNT(*), AVG(pct_uso_esporadico), SUM(n_listings_airbnb) FROM \"data/output/dataset.parquet\" GROUP BY isla').to_df())"
|
||||
```
|
||||
|
||||
## 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 con tasa de exito > 95% (listings asignados a seccion censal)
|
||||
- [x] `STATS.md` documenta: nº secciones, nº listings por isla, distribuciones, outliers
|
||||
- [x] Screenshot del mapa en Jupyter notebook como evidencia visual
|
||||
- [x] Scripts Python reproducibles en `scripts/` con comentarios sobre decisiones
|
||||
- [x] Commit final con tag `fase-1-completa`
|
||||
|
||||
## Decisiones tomadas durante la fase
|
||||
|
||||
_Llenar durante la ejecucion. Ejemplos:_
|
||||
- _Decidimos filtrar listings por `availability_365 > 60` para excluir inactivos esporadicos._
|
||||
- _Decidimos calcular "pct_uso_esporadico" como 1 - (consumo_mediano / p75 consumo), no como categoria INE directa._
|
||||
- _El join espacial asigna por punto interior al poligono; los listings a < 50m del borde se asignan al mas cercano (regla documentada)._
|
||||
|
||||
## Problemas encontrados
|
||||
|
||||
_Llenar durante la ejecucion._
|
||||
|
||||
## Proximos pasos
|
||||
|
||||
Fase 2: web MVP con Astro + MapLibre. Ver `FASE-2-web-mvp.md`.
|
||||
@@ -0,0 +1,152 @@
|
||||
# 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
|
||||
|
||||
_Llenar durante la ejecucion._
|
||||
|
||||
## Problemas encontrados
|
||||
|
||||
_Llenar durante la ejecucion._
|
||||
|
||||
## Proximos pasos
|
||||
|
||||
Fase 3: lanzamiento publico. Ver `FASE-3-lanzamiento.md`.
|
||||
@@ -0,0 +1,122 @@
|
||||
# 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
|
||||
@@ -0,0 +1,59 @@
|
||||
# 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 (pendiente ejecucion)
|
||||
- [ ] Fase 0 ejecutada
|
||||
- [ ] Fase 1 ejecutada
|
||||
- [ ] Fase 2 ejecutada
|
||||
- [ ] 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.
|
||||
@@ -0,0 +1,49 @@
|
||||
# Cases Tancades
|
||||
|
||||
Web publica que visibilitza la pressio turistica sobre el parc residencial de Balears, creuant dades oficiales d'INE (consum electric per seccio censal, com a proxy de vivenda semi-vacia) amb dades d'Inside Airbnb (listings georreferenciats).
|
||||
|
||||
Veure [PLAN.md](PLAN.md) per al plan complet i l'arquitectura.
|
||||
|
||||
## Estructura
|
||||
|
||||
```
|
||||
data/raw/ Dades originals descarregades (no commitejades)
|
||||
data/processed/ Dades intermiges del pipeline
|
||||
data/output/ Dades finals (parquet, tiles, JSON)
|
||||
docs/ Documentacio i materials de suport
|
||||
scripts/ Pipeline Python
|
||||
web/ Codi Astro de la web
|
||||
FASE-*.md Bitacora de cada fase del projecte
|
||||
```
|
||||
|
||||
## Setup rapid
|
||||
|
||||
```bash
|
||||
# Python
|
||||
uv venv .venv
|
||||
source .venv/bin/activate
|
||||
uv pip install -r requirements.txt
|
||||
|
||||
# Node
|
||||
nvm use 20
|
||||
```
|
||||
|
||||
## Estat
|
||||
|
||||
| Fase | Estat |
|
||||
|---|---|
|
||||
| Fase 0 - Setup | En curs |
|
||||
| Fase 1 - Dades | Pendent |
|
||||
| Fase 2 - Web MVP | Pendent |
|
||||
| Fase 3 - Llanament | Pendent |
|
||||
|
||||
## Fonts de dades
|
||||
|
||||
- INE - Intensitat d'us per consum electric: taula del fitxer `data/raw/viviendas vacias-hipotecas.xlsx` (full 1).
|
||||
- INE - Seccions censals de Balears: shapefile descarregat de https://www.ine.es/prodyser/cartografia/seccionado_2025/
|
||||
- Inside Airbnb - Listings Balears: http://insideairbnb.com/get-the-data/
|
||||
- Captures conferencia OHIB (12-13 nov 2025): `docs/conferencia-OHIB-2025/`
|
||||
|
||||
## Llicencia
|
||||
|
||||
A determinar. Probablement CC BY-SA 4.0.
|
||||
@@ -0,0 +1,33 @@
|
||||
# Origen de las dades en `data/raw/`
|
||||
|
||||
## `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/
|
||||
- **Fecha de descarga**: (pendiente, ejecutar en setup de Fase 0)
|
||||
- **Descripcion**: Poligons de les seccions censals per a les Illes Balears.
|
||||
- **CRS original**: ETRS89 (EPSG:4258), reprojectar a WGS84 (EPSG:4326) per a la web.
|
||||
|
||||
## Inside Airbnb listings
|
||||
|
||||
- **Origen**: Inside Airbnb (proyecto independiente que scrapea Airbnb y publica datos abiertos).
|
||||
- **URL de descarga**: http://insideairbnb.com/get-the-data/
|
||||
- **Fecha de descarga**: (pendiente, ejecutar en setup de Fase 0)
|
||||
- **Descripcion**: Listings georreferenciats (lat/lon) amb informacio de tipus, disponibilitat i preu. Snapshots separats per Mallorca, Menorca, Eivissa i Formentera.
|
||||
- **Licencia**: Creative Commons (consultar web del proyecto).
|
||||
Binary file not shown.
@@ -0,0 +1,8 @@
|
||||
pandas>=2.2
|
||||
openpyxl>=3.1
|
||||
pyarrow>=16.0
|
||||
duckdb>=1.0
|
||||
geopandas>=1.0
|
||||
shapely>=2.0
|
||||
pyproj>=3.6
|
||||
fiona>=1.10
|
||||
Reference in New Issue
Block a user