Imagínate esto: estás creando un mapa web con toda la energía del mundo. Ya instalaste Leaflet, tienes un mapa base de fondo bonito y hasta le pusiste zoom con estilo.
Pero cuando llega el momento de mostrar los datos espaciales reales ¡bam!. Te chocas con una muralla invisible que nadie te advirtió. Literalmente. ¡No sabes cómo conectarlos desde la base de datos al frontend sin usar GeoServer!
Esto es más común de lo que crees. Y sí, también me pasó. Por eso hoy te voy a mostrar cómo evitar este error que puede arruinar por completo tu proyecto.
El problema no es Leaflet, es no planear tu arquitectura
Cuando empezamos en el mundo de los mapas web, creemos que la parte difícil es hacer que el mapa se vea. Pero la verdad es que mostrar un punto en Leaflet es pan comido.
El verdadero reto no es ver el punto en el mapa, sino entender su viaje completo: desde la base de datos hasta tu pantalla, sin que pese una tonelada ni bloquee tu navegador.
Si no piensas eso desde el inicio, puedes acabar:
- Cargando muchos puntos a la vez.
- Metiendo archivos GeoJSON a mano en tu código como si fuera un Excel.
- O haciendo malabares para conectar tu frontend con una API improvisada.
¿Qué es la arquitectura de una aplicación web?
La arquitectura de una aplicación web es la estructura que define cómo interactúan entre sí los distintos componentes de un sistema para cumplir una funcionalidad.
En nuestro caso, el objetivo es mostrar datos espaciales en un mapa web y para eso se necesita una comunicación fluida entre:
- Base de datos (PostGIS): almacena los datos espaciales.
- Backend (API REST con FastAPI): recupera datos de la base y los entrega al frontend.
- Frontend (Leaflet en Angular o React): presenta los datos al usuario de forma interactiva.
Diseño recomendado para este caso
- Modelo de datos bien definido con tablas espaciales y columnas optimizadas.
- Endpoints claros en la API, que devuelvan GeoJSON con filtros eficientes.
- Frontend reactivo, que pida datos por vista y no todo de una.
Arquitectura básica para conectar base de datos al frontend
Vamos a simplificar este proceso. Piensa en tu proyecto como una cadena:
- PostGIS: Aquí vive tu información espacial, en una base de datos potente.
- API REST (FastAPI, Flask o Express): Es el mozo que va a la cocina (PostGIS) y te trae justo lo que pediste.
- Formato de salida: GeoJSON: El idioma común entre backend y frontend.
- Frontend con Leaflet (Angular, React o Vanilla JS): Tu mapa web, el que ve el usuario.
Cada eslabón tiene que funcionar bien. Si uno falla, el mapa se rompe.
Ejemplo real: cómo no hacerlo
Hace un tiempo, un colega me dijo: “Mira este mapa, está perfecto”. Y sí, visualmente era bello. Pero al abrir la consola, vi esto:
- Una petición única que cargaba TODO el contenido de una tabla con cientos de miles de puntos.
- El mapa se congelaba.
- No había forma de filtrar.
Eso pasa cuando no diseñas tu API para hacer consultas espaciales reales.
Cómo hacerlo bien: paso a paso
1. Base de datos PostGIS bien estructurada
Asegúrate de crear tus tablas con las geometrías en una columna geom y usa los tipos (para este ejemplo de puntos) geometry(Point, 4326) correctamente. Agrega índices espaciales para mejorar el rendimiento:
--CREAR LA EXTENSIÓN DE POSTGIS
CREATE EXTENSION IF NOT EXISTS postgis;
--CREAR LA TABLA
DROP TABLE IF EXISTS centros_salud;
CREATE TABLE centros_salud (
id SERIAL PRIMARY KEY,
nombre TEXT,
direccion TEXT,
telefono TEXT,
municipio TEXT,
horario TEXT,
categoria TEXT,
geom GEOMETRY(Point, 4326)
);
--INSERTAR DATOS
INSERT INTO centros_salud (nombre, direccion, telefono, municipio, horario, categoria, geom)
VALUES ('ASOCIACION CLINICA BAUTISTA', 'CL 70B 38 37', '3683136', 'BARRANQUILLA', '', 'CLINICA', ST_SetSRID(ST_MakePoint(-74.808791, 10.985125), 4326));
INSERT INTO centros_salud (nombre, direccion, telefono, municipio, horario, categoria, geom)
VALUES ('INSTITUTO DE SEGUROS SOCIALES', 'CL 36 44-12', '3514491', 'BARRANQUILLA', '6:00 A.M. - 10:00 P.M.', 'CENTRO MEDICO', ST_SetSRID(ST_MakePoint(-74.779295, 10.983346), 4326));
INSERT INTO centros_salud (nombre, direccion, telefono, municipio, horario, categoria, geom)
VALUES ('CLINICA DENTAL CARACAS', 'KR 54 70 69', '3458552', 'BARRANQUILLA', '', 'CLINICA', ST_SetSRID(ST_MakePoint(-74.800448, 10.998248), 4326));
INSERT INTO centros_salud (nombre, direccion, telefono, municipio, horario, categoria, geom)
VALUES ('HOSPITAL GENERAL DE BARRANQUILLA', 'CL 33 33-139', '3798708', 'BARRANQUILLA', '', 'HOSPITAL', ST_SetSRID(ST_MakePoint(-74.780141, 10.973411), 4326));
INSERT INTO centros_salud (nombre, direccion, telefono, municipio, horario, categoria, geom)
VALUES ('CLINICA GENERAL DEL NORTE', 'KR 48 70 22', '3564145', 'BARRANQUILLA', '', 'CLINICA', ST_SetSRID(ST_MakePoint(-74.802759, 10.994740), 4326));
--CREAR INDICES
CREATE INDEX idx_centros_geom ON centros_salud USING GIST (geom);
2. API con FastAPI y filtros espaciales
Una API bien hecha no solo devuelve datos. Devuelve los datos que necesitas en ese momento. Por ejemplo:
@app.get("/features")
def get_features(bbox: str):
minx, miny, maxx, maxy = map(float, bbox.split(','))
cur.execute("""
SELECT json_build_object(
'type', 'FeatureCollection',
'features', json_agg(
json_build_object(
'type', 'Feature',
'geometry', ST_AsGeoJSON(geom)::json,
'properties', ...
)
)
)
FROM centros_salud
WHERE geom && ST_MakeEnvelope(%s, %s, %s, %s, 4326);
""", (minx, miny, maxx, maxy))
Conecta tu Base de Datos:
import psycopg2
def get_connection():
return psycopg2.connect(
host="localhost",
database="gisdb",
user="postgres",
password="postgres"
)
3. Frontend con Leaflet que consulta según la vista
En vez de cargar todo de una, carga por vista:
map.on('moveend', () => {
const bounds = map.getBounds();
const bbox = [
bounds.getWest(), bounds.getSouth(),
bounds.getEast(), bounds.getNorth()
].join(',');
fetch(`/features?bbox=${bbox}`)
.then(res => res.json())
.then(data => L.geoJSON(data).addTo(map));
});
Esto hace que tu app sea ligera, rápida y fácil de escalar.
Un ejemplo real y simple
Supongamos que tienes un mapa de centros de salud en Barranquilla. Desde FastAPI creas un endpoint /centros, lo conectas con tu base PostGIS, y devuelves un GeoJSON. Luego, desde Leaflet lo consumes y pintas puntos con colores según la categoría.
¡Listo! Ahora tu app está optimizada, no se congela, y puedes escalarla con filtros, dashboards o capas adicionales.
La prisa por ver el mapa funcionando nos hace cometer errores. Pero si desde el principio diseñas cómo vas a conectar tu base de datos desde backend a frontend, te vas a ahorrar dolores de cabeza, tiempo y algunos gritos a la pantalla.
Empieza simple. Crea una API que devuelva datos espaciales por consulta. Usa GeoJSON. Y haz que tu frontend pida solo lo necesario.
Aquí puedes acceder a los scripts completos.
🎁 Descarga mi guía gratuita para crear tu primer mapa con Leaflet desde cero: https://johagis.com/descargar-guia
👉 ¿Quieres aprovechar al máximo este contenido? No te pierdas ni un segundo, ¡dale play hasta el final!
