🌍 Sitio web oficial: www.todosnuestrospumas.es
Mapa interactivo de Ford Pumas (1997-2002).
Página estática que ubica Ford Pumas en un mapa con iconos coloreados según el color de cada coche. Incluye filtros por color y motor, leyenda dinámica, agrupación por clusters y un modal informativo sobre el proyecto y el vehículo. Compatible con escritorio, tablet y móvil; los paneles se reposicionan automáticamente al girar el dispositivo. La interfaz se adapta al idioma del navegador (español, inglés, francés, alemán y portugués).
- Leaflet — mapa interactivo
- Leaflet.markercluster — clusters
- OpenStreetMap — tiles del mapa
- Nominatim — geolocalización de ciudades no incluidas en el gazetteer offline
- Google Sheets API — descarga de respuestas del formulario de registro
/
├── index.html # Página principal (HTML + CSS)
├── static/
│ └── app.js # Lógica de la aplicación (JS)
├── CNAME # Dominio personalizado para GitHub Pages
├── site.webmanifest # Manifiesto PWA
├── favicon.ico / favicon-*.png # Favicons
├── apple-touch-icon.png
├── android-chrome-*.png
├── data/
│ ├── pumas.csv # Lista pública de vehículos (ciudad, país, motor, color)
│ └── gazetteer.json # Base de datos offline de coordenadas por ciudad
├── docs/
│ └── SPECS.md # Especificaciones técnicas (generación de iconos, colores)
├── icons/
│ └── puma_[color].png # Iconos del coche por color
└── scripts/
├── update_from_sheets.py # Actualiza pumas.csv desde Google Sheets (formulario)
├── convert_csv.py # Alternativa: convierte CSV local privado al formato público
└── gen_icons.py # Genera iconos PNG por color a partir de la silueta base
Requiere Poetry.
poetry install
poetry run serve # abre http://localhost:8080
poetry run serve 9000 # puerto alternativo
poetry run serve 8080 --lan # accesible desde otros dispositivos en la misma WiFiCon --lan, el servidor también imprime la URL accesible desde la red local (útil para probar la web en el móvil o la tablet sin desplegar).
Para regenerar los iconos PNG (solo si se añaden colores nuevos):
poetry install --extras icons # instala numpy y Pillow
poetry run python scripts/gen_icons.pyLos datos se recogen a través de un formulario de Google Forms (enlace visible en el mapa). Las respuestas se almacenan en una hoja de cálculo privada de Google Sheets accesible solo para el administrador.
- Copia
.env.examplea.envy rellena el valor:cp .env.example .env # edita .env y añade el SHEET_ID de tu hoja de Google Sheets - Entra en console.cloud.google.com
- Activa la Google Sheets API en tu proyecto
- Crea credenciales: OAuth client ID → Desktop app
- Descarga el JSON y guárdalo en
~/.config/tpumas/credentials.json
⚠️ Nunca subas.env,credentials.jsonni ningún token al repositorio. El.gitignoreya los excluye como medida de seguridad adicional.
# Descarga respuestas y regenera data/pumas.csv
poetry run python scripts/update_from_sheets.py
# Vista previa sin escribir nada
poetry run python scripts/update_from_sheets.py --dry-runLa primera vez se abrirá el navegador para autenticarse con Google. El token se guarda en ~/.config/tpumas/authorized_user.json y no hace falta volver a autenticarse.
Si hay ciudades nuevas en los datos, el script las geocodifica automáticamente via Nominatim y actualiza data/gazetteer.json.
Después de actualizar, publicar los cambios:
git add data/pumas.csv data/gazetteer.json
git commit -m "Actualiza datos del mapa"
git pushLas respuestas del formulario se pueden notificar por email mediante un script de Google Apps Script asociado a la hoja de respuestas (Extensiones → Apps Script):
function onFormSubmit(e) {
const row = e.values;
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
let body = "Nueva respuesta en el formulario de Todos Nuestros Pumas:\n\n";
headers.forEach((header, i) => {
body += `${header}: ${row[i] || "-"}\n`;
});
MailApp.sendEmail({
to: SpreadsheetApp.getActiveSpreadsheet().getOwner().getEmail(),
subject: "🐾 Nuevo Puma registrado",
body: body
});
}Actívalo en Activadores → Al enviar el formulario.
Copyright (C) 2026 Nedemin
Este proyecto se distribuye bajo la licencia GNU General Public License v3.0 o posterior. Puedes copiarlo, modificarlo y distribuirlo siempre que mantengas la misma licencia en los trabajos derivados.
Ver el archivo LICENSE para el texto completo.