El usuario sube medios
|
v
Extracción EXIF en cliente (exifr) --> GPS, timestamp, dispositivo
|
v
Verificación de calidad pre-ID --> advertencia de desenfoque/oscuridad
|
|--- Planta detectada? ---------------> PlantNet Pro API
| (78K especies, confianza)
|
|--- Sonido de ave? ------------------> BirdNET
| (licencia comercial)
|
+--- Imagen/video general ------------> Gemini 2.5 Flash-Lite
|
+- conf >= 0.8 --> Resultado
|
+- conf < 0.8 --> Claude Haiku 4.5
|
+- conf >= 0.7 --> Resultado
|
+- Cola experta --> Sonnet
Respaldo offline:
EfficientNet-Lite0 INT8 ONNX (<3MB, top 500 especies)
+ Paquetes regionales (Oaxaca/Yucatán 10-30MB, carga diferida en IndexedDB)
## Modelo de Costos
| Escala | Costo mensual | Por usuario |
|--------|--------------|-------------|
| 10K MAU | ~$2,000 | $0.20 |
| 50K MAU | ~$6,000 | $0.12 |
| 100K MAU | ~$11,500 | $0.12 |
*Incluye: Supabase Pro + R2 + ~500K llamadas Claude Haiku + 600K PlantNet Pro + primera pasada Gemini + monitoreo*
**Modelo freemium:** 10 IDs/día gratis · $5/mes ilimitado + revisión experta · $200–2,000/mes institucional
## Esquema de Base de Datos (tablas principales)
```sql
-- Observación principal
observations (
id uuid PK,
observer_id uuid FK users,
observed_at timestamptz,
location geography(Point, 4326), -- PostGIS geography
location_obscured geography(Point), -- legible públicamente, difuso
habitat_type varchar,
-- Auto-enriquecimiento ambiental
moon_phase varchar, moon_illumination float,
precipitation_24h_mm float, ndvi_value float,
-- Extraído de EXIF
captured_at timestamptz, device_make varchar,
-- Particionado mensualmente vía pg_partman
)
-- Identificaciones IA
identifications (
id uuid PK,
observation_id uuid FK,
taxon_id uuid FK,
confidence float,
source varchar, -- 'plantnet'|'birdnet'|'claude_haiku'|'human'
validated_by uuid FK users,
is_research_grade boolean
)
-- RLS de ubicación sensible
-- location: auth.uid() = observer_id OR is_credentialed_researcher()
-- location_obscured: lectura pública (función IMMUTABLE obscure_point())
```
## Restricciones PWA en iOS
iOS Safari eliminará tu PWA si ignoras esto:
| Restricción | Mitigación |
|-------------|-----------|
| Evicción de almacenamiento ITP 7 días | `navigator.storage.persist()` al instalar |
| Límite suave de caché ~50MB | Mantener caché inicial bajo 30MB; cargar paquetes regionales de forma diferida |
| Sin API de Background Sync | Vaciar cola en cada apertura de la app |
| Web Push requiere A2HS | Solicitar agresivamente Agregar a Pantalla de Inicio |
| WebGPU solo Safari 26+ | Fallback WASM en ONNX Runtime Web |
| DMA de la UE rompe Web Push (iOS 17.4) | Wrapper Capacitor para v1.2 |
## Mapas Offline
```
Zoom 0–10: ~250MB vista general (México, pre-incluido)
Zoom 11–14: el usuario descarga chunks de 50km de radio (~20–60MB cada uno)
→ almacenados en blob storage de Dexie
Stack: MapLibre GL JS + formato pmtiles de protomaps
Autoalojado en Cloudflare R2 (cero egreso)
```