Skip to content
Proyecto propio · Mapas y 3D

GeoNarrator Studio

Editor visual de historias sobre mapas, para quien sabe qué contar pero no va a escribir JavaScript

Mapbox GL JSTerreno 3DGeoJSONScrollytellingEstado con migracionesSin backend
El proyecto

GeoNarrator Studio es un editor de scrollytelling geográfico. Una historia es una secuencia de escenas, y cada escena guarda un texto más una posición de cámara; en modo preview el mapa vuela de una a la siguiente con el scroll. Incluye búsqueda de lugares, reordenamiento de escenas arrastrando, carga de capas GeoJSON propias con estilos y leyenda automática, cinco estilos de mapa con terreno 3D y proyección de globo, export e import de la historia como JSON, y embed en iframe mediante URL. Pensado para periodismo de datos y docencia.

Por qué existe

Las herramientas para contar historias sobre mapas se van a dos extremos. Por un lado librerías como Mapbox GL o deck.gl, que dan control total a cambio de programar. Por el otro, plantillas cerradas donde eliges tres opciones y hasta ahí. En el medio queda mucha gente que sabe exactamente qué mostrar y en qué orden, pero no va a escribir JavaScript para lograrlo.

Cómo lo construí

Decidí no poner backend. El estado vive en el navegador, la historia se exporta como JSON y el embed viaja dentro de la URL. Eso funciona hasta que alguien carga un GeoJSON grande que no cabe en una URL, y ahí la herramienta avisa en vez de generar un link roto en silencio. Ese es el punto donde un backend se justificaría, y no antes. La parte que más me costó fue el estado persistido. Al guardar en localStorage, el esquema se vuelve público y necesita migraciones, igual que una base de datos. Zustand rehidrata después del primer render, así que lo guardado pisa los defaults del código y cambiar un valor por defecto solo alcanza a visitantes nuevos.

Stack y decisiones técnicas

Next.js 14 con App Router y export estático. Mapbox GL JS vía react-map-gl, con terreno 3D y proyección de globo. Estado en Zustand persistido en localStorage con migraciones versionadas. Tailwind y Framer Motion. Desplegado en Cloudflare Pages. Sin backend a propósito, así que la historia vive en el navegador, se exporta como JSON y el embed viaja dentro de la URL.

Reflexión

Una migración tiene que comparar contra un snapshot exacto de lo que escribió la versión anterior, campo por campo. Probé el atajo de detectar el contenido de demo por los ids de los objetos, y falla en cuanto alguien edita sin agregar. Ese atajo borra trabajo real de una persona, así que prefiero el código más largo.