→
Arquitectura: Client-Side AI (sin backend)
Firebase AI Logic actúa de proxy seguro — no hay servidor intermedio que gestionar
🛒
CultivaShop
React + Vite
→
🔥
Firebase AI Logic
SDK client-side
→
✦
Gemini Developer API
Gemini 2.5 Flash
+
🛡️
App Check
reCAPTCHA Enterprise
Sin backend propio: Firebase AI Logic gestiona la autenticación y el rate-limiting.
El SDK web llama directamente a Gemini de forma segura mediante App Check, sin exponer API keys al cliente.
1
Setup e Instalación
Pasos de configuración inicial del proyecto CultivaShop
PASO 1
Instalar Firebase
npm install -g firebase@latest
PASO 2
Verificar proyecto
firebase projects:list
PASO 3
Verificar apps
firebase apps:list
PASO 4
Init AI Logic
firebase init ailogic
PASO 5
Habilita Blaze plan
Firebase Console
CRÍTICO — Backend Provisioning: Para todos los platforms DEBES ejecutar
firebase init ailogic para provisionar el servicio. Solo flutterfire configure
NO habilita el servicio de IA y causará errores PERMISSION_DENIED.
src/lib/firebase.js — Inicialización Firebase AI Logic para CultivaShop
JavaScript
import { initializeApp } from "firebase/app"; import { getAI, getGenerativeModel, GoogleAIBackend } from "firebase/ai"; import { initializeAppCheck, ReCaptchaEnterpriseProvider } from "firebase/app-check"; import { getRemoteConfig, getValue, fetchAndActivate } from "firebase/remote-config"; // Configuración del proyecto CultivaShop en Firebase const firebaseConfig = { apiKey: "AIzaSy...cultivashop_key", authDomain: "cultivashop-prod.firebaseapp.com", projectId: "cultivashop-prod", storageBucket: "cultivashop-prod.appspot.com", messagingSenderId: "847392018456", appId: "1:847392018456:web:a3f891bc...", }; const app = initializeApp(firebaseConfig); // 🛡️ App Check con reCAPTCHA Enterprise (OBLIGATORIO para producción) initializeAppCheck(app, { provider: new ReCaptchaEnterpriseProvider("6Le...cultivashop_recaptcha_key"), isTokenAutoRefreshEnabled: true, }); // Remote Config: modelo dinámico sin redeploy const remoteConfig = getRemoteConfig(app); remoteConfig.defaultConfig = { gemini_model: "gemini-2.5-flash", }; await fetchAndActivate(remoteConfig); const modelName = getValue(remoteConfig, "gemini_model").asString(); // Inicializar AI Logic con Gemini Developer API const ai = getAI(app, { backend: new GoogleAIBackend() }); const generationConfig = { maxOutputTokens: 2048, temperature: 0.7, topP: 0.95, topK: 40, }; export const model = getGenerativeModel(ai, { model: modelName, // Desde Remote Config, sin hardcodear generationConfig, });
2
Caso de uso 1 — Asistente de Cultivo (Chat multi-turno)
Responde dudas sobre técnicas, nutrientes y equipamiento con historial de conversación
src/hooks/useCultivaChat.js — Chat con streaming y historial
JavaScript
import { useState, useRef } from "react"; import { model } from "../lib/firebase"; const SYSTEM_PROMPT = `Eres el asistente experto de CultivaShop, tienda de cultivo indoor. Ayudas a cultivadores con: técnicas hidropónicas, nutrientes, control de plagas, fases de cultivo, iluminación LED y vertical farming. Responde siempre en español, de forma amigable y precisa.`; export function useCultivaChat() { const [messages, setMessages] = useState([]); const [isStreaming, setIsStreaming] = useState(false); const chatRef = useRef(null); // Iniciar sesión de chat con system prompt de CultivaShop const initChat = () => { chatRef.current = model.startChat({ history: [{ role: "user", parts: [{ text: SYSTEM_PROMPT }], }, { role: "model", parts: [{ text: "¡Hola! Soy el asistente de CultivaShop. ¿En qué te ayudo hoy?" }], }], }); }; // Enviar mensaje con streaming (efecto de escritura en tiempo real) const sendMessage = async (userText) => { if (!chatRef.current) initChat(); setIsStreaming(true); // Añadir mensaje del usuario al historial UI setMessages(prev => [...prev, { role: "user", text: userText }]); let aiText = ""; setMessages(prev => [...prev, { role: "ai", text: "", streaming: true }]); // Streaming: cada chunk actualiza la UI en tiempo real const result = await chatRef.current.sendMessageStream(userText); for await (const chunk of result.stream) { aiText += chunk.text(); setMessages(prev => { const updated = [...prev]; updated[updated.length - 1] = { role: "ai", text: aiText, streaming: true }; return updated; }); } setIsStreaming(false); }; return { messages, isStreaming, sendMessage }; }
Tengo mis tomates cherry en semana 4 de vegetativo. ¿Qué nutrientes necesitan y en qué dosis?
✦ Asistente CultivaShop
En semana 4 de vegetativo tus tomates cherry necesitan sobre todo Nitrógeno (N) para el crecimiento foliar. Te recomiendo este esquema:
🌿 N-P-K base: 3-1-2 (alto N, bajo P y K)
💧 EC objetivo: 2.0–2.4 mS/cm | pH: 5.8–6.2
🔬 Micronutrientes: Calcio 150 ppm + Magnesio 50 ppm
En nuestra tienda tienes el Pack Vegetativo Pro de BioBizz que cubre todo esto.
🌿 N-P-K base: 3-1-2 (alto N, bajo P y K)
💧 EC objetivo: 2.0–2.4 mS/cm | pH: 5.8–6.2
🔬 Micronutrientes: Calcio 150 ppm + Magnesio 50 ppm
En nuestra tienda tienes el Pack Vegetativo Pro de BioBizz que cubre todo esto.
3
Caso de uso 2 — Diagnóstico de Planta por Foto (Multimodal)
El usuario sube una foto, Gemini analiza síntomas y recomienda tratamiento
src/components/PlantDoctor.js — Análisis multimodal de imágenes
JavaScript
import { model } from "../lib/firebase"; // Convierte File a parte inlineData para Gemini async function fileToInlineData(file) { return new Promise((resolve) => { const reader = new FileReader(); reader.onloadend = () => resolve({ inlineData: { data: reader.result.split(",")[1], mimeType: file.type, // image/jpeg, image/png... } }); reader.readAsDataURL(file); }); } export async function diagnosePlant(imageFile) { const imagePart = await fileToInlineData(imageFile); const prompt = `Eres un experto en fitosanidad y cultivo indoor. Analiza esta foto de planta y proporciona: 1. Síntomas observados y probable diagnóstico 2. Causa raíz (deficiencia, plaga, enfermedad, riego...) 3. Tratamiento recomendado con productos específicos 4. Medidas preventivas para evitar recaídas Responde en español, de forma práctica y concreta.`; const result = await model.generateContent([prompt, imagePart]); return result.response.text(); } // Nota: para archivos >20 MB usar Cloud Storage for Firebase en lugar de inline data
4
Caso de uso 3 — Recomendación de Nutrientes (Structured JSON Output)
Gemini devuelve un plan de nutrición estructurado, parseable directamente
src/services/nutrientPlanner.js — JSON schema enforcement
JavaScript
import { getGenerativeModel, Schema } from "firebase/ai"; import { ai } from "../lib/firebase"; // Modelo configurado para salida JSON estructurada const nutrientModel = getGenerativeModel(ai, { model: "gemini-2.5-flash", generationConfig: { responseMimeType: "application/json", responseSchema: Schema.object({ properties: { planta: Schema.string(), fase: Schema.string(), semana: Schema.integer(), ec_objetivo: Schema.number(), ph_objetivo: Schema.number(), npk: Schema.object({ properties: { N: Schema.number(), P: Schema.number(), K: Schema.number(), } }), productos_recomendados: Schema.array({ items: Schema.object({ properties: { nombre: Schema.string(), dosis_ml_L: Schema.number(), frecuencia: Schema.string(), } }) }), advertencias: Schema.array({ items: Schema.string() }), } }), } }); export async function getNutrientPlan({ planta, fase, semana, sistema }) { const prompt = `Genera un plan de nutrición para: - Planta: ${planta} | Fase: ${fase} | Semana: ${semana} - Sistema: ${sistema} (hidropónico/tierra/coco) Devuelve exclusivamente el JSON con el esquema especificado.`; const result = await nutrientModel.generateContent(prompt); return JSON.parse(result.response.text()); // → objeto tipado, sin parse errors }
Input: tomates cherry, fase vegetativa, semana 4, sistema hidropónico
{
"planta": "tomate cherry",
"fase": "vegetativo",
"semana": 4,
"ec_objetivo": 2.2,
"ph_objetivo": 6.0,
"npk": { "N": 180, "P": 60, "K": 120 },
"productos_recomendados": [
{ "nombre": "BioBizz Grow", "dosis_ml_L": 4, "frecuencia": "cada riego" },
{ "nombre": "Calmag Pro", "dosis_ml_L": 1.5, "frecuencia": "2x semana" },
{ "nombre": "Rhizotonic", "dosis_ml_L": 0.5, "frecuencia": "semanal" }
],
"advertencias": [
"No mezclar Calmag con fosfatos en el mismo depósito",
"Medir EC antes y después de añadir nutrientes"
]
}
5
Funcionalidades implementadas en CultivaShop
Resumen de capacidades Firebase AI Logic activas
Chat multi-turno
Asistente con historial de conversación, contexto persistente y system prompt de CultivaShop.
model.startChat()
Streaming SSE
Respuestas en tiempo real con efecto de escritura. UX fluida sin esperar respuesta completa.
generateContentStream()
Análisis Visual
Diagnóstico de plagas y enfermedades por foto. Multimodal con Base64 inline data.
inlineData + mimeType
JSON Estructurado
Planes de nutrición con Schema tipado. Parse seguro, sin errores de formato.
responseMimeType: json
App Check
Protección contra abuso de API. reCAPTCHA Enterprise verifica clientes legítimos.
ReCaptchaEnterpriseProvider
Remote Config
Modelo Gemini configurable sin redeploy. Cambia versión desde Firebase Console.
getValue(rc, "gemini_model")
6
Seguridad y Producción
Requisitos obligatorios antes de lanzar CultivaShop a producción
CRÍTICO — App Check es OBLIGATORIO en producción. Sin él, cualquier cliente puede usar tu cuota de API
y acceder a tus recursos de Firebase. Implementar antes del lanzamiento, sin excepción.
App Check
reCAPTCHA Enterprise verifica que las peticiones vienen de la app real. Bloquea bots y abuso de quota.
No exponer API Keys
La firebaseConfig del cliente es pública por diseño, pero App Check impide uso no autorizado.
Remote Config
No hardcodear nombres de modelo. Actualizar modelo desde Firebase Console sin redeploy.
Firebase Rules
Definir reglas de Firestore/Storage para limitar acceso solo a usuarios autenticados.
7
Elección de Proveedor API
Gemini Developer API vs Vertex AI Gemini API para CultivaShop
| Característica | Gemini Developer API | Vertex AI Gemini API | Recomendación |
|---|---|---|---|
| Tier gratuito | Sí — RPM y tokens gratuitos | No (Blaze plan requerido) | Dev API para MVP |
| Plan Firebase requerido | Spark (gratuito) para test | Blaze (pay-as-you-go) | Spark → Dev API |
| Escalabilidad | Limitada por rate limits | Enterprise, sin límites | Vertex AI a escala |
| Complejidad setup | Baja (1 comando) | Media (billing, IAM) | Dev API primero |
| SLA producción | Sin garantía | 99.9% uptime SLA | Vertex AI en prod |
| Cambio de backend | Una línea de código: GoogleAIBackend() → VertexAIBackend() | Sin fricción | |
Estrategia CultivaShop: Arrancar con Gemini Developer API (tier gratuito) para el MVP.
Cuando superen 60 rpm o necesiten SLA, migrar a Vertex AI cambiando solo
new GoogleAIBackend()
→ new VertexAIBackend() en un fichero. Sin refactoring.✓
Checklist de lanzamiento
Todos los puntos a verificar antes de poner CultivaShop IA en producción
Pre-producción
Firebase project creado y App registradacultivashop-prod en Firebase Console
firebase init ailogic ejecutadoHabilita Gemini Developer API en el proyectoPlan Blaze activado para funciones avanzadasRequerido para imagen generation con Nano Banana
App Check configurado con reCAPTCHA EnterpriseCRÍTICO: Implementar antes del launch público
Remote Config con clave
gemini_model configuradaValor por defecto: gemini-2.5-flashManejo de errores y rate limits implementado429 Too Many Requests, 413 para archivos grandes
Test E2E del flujo completo de asistenteChat, multimodal, JSON output