Duración estimada: 2 horas
Objetivos de aprendizaje
- Capturar datos de formularios y prevenir recargas con event.preventDefault()
- Manipular el DOM para insertar mensajes dinámicamente
- Realizar peticiones POST a APIs de IA con fetch
- Usar async/await para manejar respuestas del modelo
- Entender los riesgos de seguridad al exponer claves API en el frontend
Sesión 23 - Chat con Gemini desde Frontend
Contenidos de la Sesión
En esta sesión se ha construido un chat sencillo en el navegador que:
- captura el texto del usuario desde un
<form> - pinta los mensajes en pantalla
- hace una petición
fetcha la API de Gemini - muestra la respuesta del modelo en el chat
Se ha reutilizado la base visual del tutorial de Socket.IO (solo HTML/CSS), y se ha implementado la lógica en JavaScript con addEventListener, async/await y fetch.
El ejemplo de la sesión está en: chat/
1. Estructura base del chat
La interfaz usa:
- una lista
<ul id="messages">para los mensajes - un formulario
<form id="form"> - un
<input name="textUsuario">para el texto del usuario
Cuando se envía el formulario:
- se evita el recargo con
event.preventDefault() - se lee el texto con
new FormData(form).get("textUsuario") - se añade un
<li>del usuario al chat - se llama a Gemini y se añade otro
<li>con la respuesta
2. Petición a Gemini con fetch
La llamada se hace con method: "POST", cabeceras JSON y la API key en x-goog-api-key:
const response = await fetch(url, {
method: "POST",
headers: {
"x-goog-api-key": API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify(datos),
});
Después se transforma la respuesta con await response.json() y se extrae el texto:
return data.candidates[0].content.parts[0].text;
Tip
El patrón async/await hace el código asíncrono más legible que encadenar muchos .then() / .catch().
3. Prompt dinámico
El ejemplo concatena el texto del usuario en el payload:
text: "eres un asistente y te han preguntado: " + texto + ". Responde con pocas palabras"
Esto permite enviar cada mensaje del formulario como entrada al modelo.
Note
En un proyecto real conviene mantener instrucciones del sistema separadas del input del usuario para tener más control del comportamiento del modelo.
4. Renderizado en el DOM
Cada mensaje se representa como un li:
class="user"para el mensaje del usuarioclass="gpt"para la respuesta del modelo
La construcción se hace con document.createElement("li"), innerText y appendChild.
5. Aviso importante de seguridad
Warning
El ejemplo de esta sesión es intencionadamente vulnerable para aprendizaje: la API key está en el frontend y cualquiera puede verla desde el navegador.
Important
En producción, las claves privadas nunca deben ir en cliente. La llamada a Gemini debe pasar por un backend (servidor propio o función serverless) que guarde la key en variables de entorno.
6. Estructura de archivos de la sesión
session23/
├── README.md
└── chat/
├── index.html — estructura del chat (lista + formulario + input)
├── index.js — lógica de envío, renderizado y llamada a Gemini
└── style.css — estilos del chat
Resumen
En esta sesión hemos practicado:
- ✅ formularios y eventos (
submit,preventDefault) - ✅ lectura de datos con
FormData - ✅ creación de nodos con
createElement+appendChild - ✅ llamadas HTTP con
fetch(POST, headers y body JSON) - ✅ asincronía con
async/await - ✅ consumo básico de una API de IA (Gemini)
- ✅ identificación de un riesgo real: exponer una API key en frontend
Recursos Adicionales
- Google AI Studio
- Gemini API Quickstart
- MDN - Fetch API
- MDN - async function
- Socket.IO Tutorial (base visual usada en clase)
Ejercicios prácticos
-
1. Mejorar el chat de Gemini
Añade historial de conversación, manejo de errores mejorado y validación de entrada.
-
2. Mover la lógica a un backend
Refactoriza el chat para que la llamada a Gemini se haga desde un servidor backend, ocultando la API key.