FarmaMap: Farmacias de Guardia en Tiempo Real
Estamos construyendo una PWA que encuentra la farmacia de guardia más cercana en 3 segundos. Para toda España. Desde cualquier dispositivo. Con datos oficiales, modo offline, IA conversacional y coste de infraestructura cero — el segundo producto de salud de Cadences, junto a NutriNen.
Un producto de Cadences · Junto a NutriNen
1 El problema que nadie ha resuelto bien
Son las 23:40 de un domingo. Tu hijo tiene fiebre. Necesitas ibuprofeno infantil. Abres Google y buscas "farmacia de guardia cerca".
Lo que encuentras: una web del colegio de farmacéuticos de tu provincia hecha en 2008, un PDF escaneado con los turnos del mes, o una app llena de anuncios con datos de hace tres días. 1.5 millones de búsquedas al mes de "farmacia de guardia" en España — y ninguna solución lo resuelve de verdad.
Tras construir NutriNen — donde aprendimos a producir herramientas de salud que capturan tráfico orgánico masivo con coste cero — nos dimos cuenta de que este problema tiene exactamente las mismas propiedades: demanda enorme, soluciones actuales penosas, y ejecutable con el stack que ya tenemos.
| Solución actual | Problema |
|---|---|
| Webs de colegios farmacéuticos | UX de los 2000, no responsive, datos dispersos por provincia |
| Google Maps "farmacia" | No distingue guardia vs abierta vs cerrada |
| Apps existentes | Datos desactualizados, ads invasivos, solo Android o solo iOS |
| PDFs del BOE / boletines | Formato no parseado, requiere descarga, imposible buscar |
2 La visión: 3 segundos para encontrar tu farmacia
FarmaMap es una Progressive Web App — funciona como app nativa cuando la instalas, pero también como web cuando la abres desde Google. Un único desarrollo que cubre iOS, Android, desktop y web. Sin App Store fees. Sin Apple Developer Program. Sin fragmentación.
💡 Value Proposition
"Encuentra la farmacia de guardia más cercana en 3 segundos. En cualquier ciudad de España. Desde cualquier dispositivo."
Mapa interactivo
Pins con color por estado: verde (abierta), azul (guardia), gris (cerrada). Clusters inteligentes. Geolocalización automática.
Offline-first
Service Worker cachea farmacias cercanas y map tiles. Funciona sin conexión. Banner "datos de hace Xh" cuando está offline.
IA conversacional
"¿Hay farmacia 24h cerca de Atocha?" — chatbot RAG con datos en tiempo real. Misma arquitectura que el chatbot de Codex.
SEO masivo
~30.000 páginas estáticas indexables: cada farmacia, municipio, provincia y CCAA. Schema.org Pharmacy en cada ficha.
3 Por qué ahora, por qué nosotros
FarmaMap no es un side project que necesita levantar infra desde cero. Todo lo que necesitamos ya existe en Cadences: D1 para datos, Workers para API edge, KV para cache, Vectorize para IA, Cron Workers para scraping automático y Synapse Studio para el admin. El coste marginal de añadir este producto es literalmente cero a nivel de infraestructura.
Además, con NutriNen hemos probado un patrón que funciona: herramientas de salud gratuitas que capturan tráfico orgánico masivo. NutriNen genera miles de visitas mensuales con 29 herramientas SEO que no cuestan nada de servir. FarmaMap replica este modelo pero con una ventaja adicional: las búsquedas "farmacia de guardia [ciudad]" son transaccionales — el usuario necesita ir a una farmacia ahora, lo que abre oportunidades de monetización directas.
🔗 Conexión NutriNen + FarmaMap
Mismo stack: Astro 5 + React + Tailwind + Cloudflare (Workers, D1, KV, Vectorize)
Mismo patrón: Herramientas gratuitas → tráfico orgánico → monetización indirecta
Mismo vertical: Ambos viven en el espacio de salud familiar
Cross-pollination: Un padre buscando farmacia de guardia para su hijo es exactamente el usuario de NutriNen. Y viceversa.
4 Arquitectura edge-native
FarmaMap se despliega como storefront de Cadences — exactamente igual que Codex, GoViajes o cualquier otro. La diferencia es que tiene un data pipeline de scraping que alimenta la base de datos cada 6 horas con fuentes oficiales de colegios farmacéuticos.
PWA con Service Worker (Workbox), IndexedDB para cache local, Mapbox GL JS para mapas interactivos. SSG para ~30K páginas estáticas (SEO). React islands para componentes dinámicos: mapa, búsqueda, filtros.
8 endpoints REST bajo /api/farmamap/*. Búsqueda geoespacial por geohash (sin extensiones GIS), full-text search (FTS5), chat IA y estadísticas. Cache con KV + CDN headers.
Scrapers por CCAA con adapter pattern. Scrape → Parse → Normalize → Geocode → Geohash → Dedupe → Upsert en D1. Alertas en Synapse si una fuente falla.
D1: 5 tablas (pharmacies, schedules, data_sources, favorites, analytics). KV: cache de guardia diaria por provincia. Vectorize: embeddings para chatbot IA. Todo gratis en el free tier de Cloudflare.
5 El truco del geohash: búsqueda espacial sin PostGIS
D1 es SQLite — no tiene extensiones geoespaciales. Pero no necesitamos PostGIS para buscar "farmacias cerca de mí". Usamos geohash: un sistema que codifica coordenadas GPS en un string alfanumérico donde los prefijos comunes indican proximidad geográfica.
-- Almacenamos geohash de 7 chars (~76m precisión)
-- pharmacies.geohash = 'ezjmgpu'
-- Query "farmacias a ~1.2km": prefijo de 6 chars
SELECT * FROM farmamap_pharmacies
WHERE geohash LIKE 'ezjmgp%'
ORDER BY geohash;
-- Query "farmacias a ~2.4km": prefijo de 5 chars
SELECT * FROM farmamap_pharmacies
WHERE geohash LIKE 'ezjmg%'
AND is_24h = 1 -- solo 24h
ORDER BY geohash; | Prefijo | Precisión | Radio aprox. | Uso |
|---|---|---|---|
| 4 chars | ±20 km | Ciudad | Búsqueda provincial |
| 5 chars | ±2.4 km | Barrio | "Cerca de mí" en ciudad |
| 6 chars | ±610 m | Manzanas | "Muy cerca" walking |
| 7 chars | ±76 m | Calle | Almacenamiento |
El cálculo fino de distancia (Haversine) se hace client-side con los ~20-50 resultados que devuelve D1, no en la query SQL. Resultado: queries de <5ms en una tabla de 22.000 farmacias sin ninguna extensión GIS.
6 Data pipeline: de 17 colegios farmacéuticos a una sola API
España no tiene una API centralizada de farmacias. Cada Comunidad Autónoma tiene su propio sistema, gestionado por su Colegio Oficial de Farmacéuticos. Eso significa que necesitamos un scraper adaptado por fuente — pero con un patrón común: adapter pattern donde cada módulo exporta scrape(), parse() y normalize().
Colegios farmacéuticos (COFM, COFB, MICOF...), portales de datos abiertos autonómicos, OpenStreetMap como seed complementario.
Cada fuente tiene su formato. Normalizamos: nombres (Title Case), direcciones (Av. → Avenida), teléfonos (+34), horarios (JSON estándar).
Muchas fuentes no incluyen lat/lng. Geocodificamos con Mapbox (batch), cacheamos en D1 para no repetir, calculamos geohash de 7 chars.
Exact match (source_id), fuzzy match (nombre similar + distancia <50m), merge de datos de múltiples fuentes.
Insert/update en D1, invalidar KV cache por provincia/fecha, log en data_sources con timestamp y estado.
7 30.000 páginas para Google: la estrategia SEO
La misma lección que NutriNen: el SEO orgánico no es un canal de marketing — es el producto mismo. Cada farmacia es una página. Cada municipio es una página. Cada provincia es una página. Google indexa todo y el usuario llega directamente a lo que busca.
| Tipo de página | Ejemplo de URL | Volumen | Target keyword |
|---|---|---|---|
| Ficha farmacia | /farmacia/garcia-lopez-gran-via-madrid | ~22.400 | "farmacia [nombre]" |
| Municipio | /municipio/alcala-de-henares | ~8.131 | "farmacia guardia [municipio]" |
| Provincia | /provincia/madrid | 52 | "farmacias guardia [provincia]" |
| Comunidad | /comunidad/comunidad-de-madrid | 17 | "farmacias [CCAA]" |
{
"@context": "https://schema.org",
"@type": "Pharmacy",
"name": "Farmacia García López",
"address": {
"@type": "PostalAddress",
"streetAddress": "Calle Gran Vía, 42",
"addressLocality": "Madrid",
"postalCode": "28013"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": 40.420041,
"longitude": -3.705764
},
"openingHoursSpecification": [...],
"telephone": "+34 91 123 4567"
} 📊 Keywords de oro
8 22.400 farmacias, 47M de usuarios potenciales
España tiene 22.400+ farmacias. Cada noche, miles de ellas entran en turno de guardia. El sistema de turnos es obligatorio y regulado — no es opcional. Eso significa datos estables, predecibles y de fuente pública.
La monetización tiene múltiples vectores, todos complementarios al modelo NutriNen de valor primero, ingresos después:
| Stream | Modelo | Target |
|---|---|---|
| Farmacia Destacada | €10-30/mes por posición preferente en resultados | Farmacias individuales |
| API comercial | Acceso a datos consolidados de farmacias | Empresas, apps, seguros |
| White-label | FarmaMap con branding del colegio farmacéutico | Colegios oficiales |
| Cadences upsell | Farmacias interesadas en web propia → storefront template | Farmacias digitalizándose |
9 Roadmap: de Madrid al mapa completo
Filosofía: ship fast, iterate faster. Cada fase es deployable y usable. No hay big bang release.
Validar fuentes de Madrid (COFM), descargar seed de OpenStreetMap, crear primer scraper, geocodificar farmacias sin coordenadas, cargar ~3.400 farmacias en D1.
PWA funcional con mapa interactivo, búsqueda por ubicación/texto/municipio, filtros (guardia, 24h, abiertas), fichas de farmacia con Schema.org, Service Worker offline, cron cada 6h.
Barcelona, Valencia, Sevilla, Bilbao, Zaragoza. Scrapers adaptados por CCAA. Favoritos en IndexedDB. Páginas de provincia y CCAA. Install prompt PWA. ~8.000+ farmacias.
Chatbot RAG ("¿hay farmacia 24h cerca de Atocha?"), sitemap.xml con 30K+ URLs, Open Graph, analytics ligero, push notifications opt-in.
Cobertura nacional: 22.400+ farmacias, 17 CCAA. Multi-idioma (ES/CA/EU/GL/EN). Performance a escala. Load testing.
Farmacia Destacada, API comercial, white-label para colegios, Cadences upsell, premium features.
10 Coste real: probablemente $0
Uno de los beneficios de construir sobre Cadences: el coste marginal de añadir un producto nuevo es casi nulo.
| Recurso | Free Tier | Necesitamos | Coste |
|---|---|---|---|
| Cloudflare Pages | 500 deploys/mes | ~10/mes | $0 |
| Workers (API) | 100K req/día | ~10K/día est. | $0 |
| D1 (base de datos) | 5GB storage | ~50MB | $0 |
| KV (cache) | 100K reads/día | ~5K/día | $0 |
| Vectorize (IA) | 200K vectors | ~25K vectors | $0 |
| Mapbox GL JS | 50K loads/mes | ~5K/mes est. | $0 |
| Total | $0/mes |
Si superamos el free tier (buena señal — significaría tracción real), el coste escala de forma lineal y predecible. Cloudflare Workers Paid es $5/mes + $0.50 por millón de requests adicionales.
📋 FarmaMap en números (objetivo)
Cadences Engineering
Documentación técnica del equipo de ingeniería