REFERENCIA TÉCNICA
Integración de Firebase AI Logic (Gemini Developer API) en la web de CultivaShop: texto, multimodal (análisis de plantas), streaming, JSON estructurado y seguridad con App Check. Sin backend propio — todo client-side con React + Vite.
Firebase AI Logic Gemini 2.5 Flash React + Vite App Check reCAPTCHA Enterprise Remote Config Streaming SSE
→
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 };
}
cultivashop.es/asistente
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.
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
}
API Response — Structured JSON Output
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.
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 proyecto
✅
Plan 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-flash
⬜
Manejo de errores y rate limits implementado429 Too Many Requests, 413 para archivos grandes
⬜
Test E2E del flujo completo de asistenteChat, multimodal, JSON output