Interfaz web para chat LoRa con HTML y JS

Resumen

Construir una interfaz web amigable para un chat LoRa convierte un proyecto de hardware en una experiencia de usuario real. Aquí aprenderás cómo estructurar el HTML, aplicar estilos con CSS y manejar peticiones HTTP en JavaScript para enviar y recibir mensajes entre dos tarjetas de desarrollo conectadas por radio.

Qué estructura HTML necesita una app de chat LoRa

La base es un formulario que contiene tres bloques bien definidos: cabecera, lista de mensajes y zona de escritura. Cada uno cumple un rol específico dentro de la interfaz.

  • header con el logo de Platzi centrado a 48 píxeles.
  • Sección messages que contendrá los mensajes entrantes y salientes con clases distintas para diferenciarlos visualmente.
  • textarea con el placeholder Escribe tu mensaje aquí más un botón de envío que dispara el evento submit del form.

Un detalle pequeño pero útil: cambiar el atributo lang del HTML a español para que el navegador lo detecte correctamente [00:42].

¿Por qué usar el evento submit del formulario en lugar de un onClick en el botón? Porque el evento submit captura tanto el clic en el botón como la tecla Enter dentro del textarea, cubriendo dos formas naturales de envío con una sola función.

Cómo aplicar estilos para diferenciar mensajes entrantes y salientes

El truco visual del chat está en jugar con el ancho del borde lateral de cada burbuja. Si el mensaje es entrante, el borde grueso queda a la izquierda; si lo enviaste tú, el borde grueso se mueve a la derecha.

El color primary verde se usa para textos, bordes y botones, mientras que el body recibe un fondo oscuro y márgenes en cero. El formulario funciona como un contenedor flex que ocupa toda la pantalla.

Cómo lograr que los mensajes nuevos aparezcan abajo

La lista de mensajes usa flex-direction: column-reverse combinado con overflow-y: scroll. Esta combinación hace dos cosas a la vez:

  • Los mensajes nuevos se renderizan en la parte inferior, como en cualquier app de mensajería conocida.
  • El scroll queda anclado abajo por defecto, sin necesidad de calcular posiciones manualmente.

El botón de envío resalta con fondo verde y texto negro para que sea el elemento más visible al pie del formulario.

Cómo manejar peticiones HTTP y mensajes con JavaScript

La lógica arranca obteniendo tres referencias del DOM: el formulario, el contenedor de mensajes y el input de texto. A partir de ahí se construyen funciones auxiliares que conversan con la API que ya creaste en clases anteriores.

La función fetch auxiliar valida que la respuesta sea ok. Si lo es, transforma el cuerpo a JSON; si no, devuelve un error y detiene la ejecución para evitar romper la interfaz.

Cómo funciona resetMessages y el puntero de inserción

resetMessages limpia el historial y agrega un div vacío que actúa como puntero. A partir de ese cursor invisible, cada nuevo mensaje se inserta con insertBefore, lo que mantiene el orden correcto en una lista invertida con column-reverse [03:50].

La función addMessage recibe el texto y un booleano self:

  • Si self es true, agrega la clase self a la burbuja para aplicar el estilo de mensaje saliente.
  • Si self es false, deja la clase base y la burbuja se renderiza como entrante.
  • Después ejecuta scrollTo para garantizar que la vista siempre muestre el mensaje más reciente.
  • Reasigna el último mensaje insertado al puntero para que insertBefore siga funcionando en la próxima llamada.

¿Qué hace encodeURIComponent en este chat? Codifica el texto del mensaje a formato URL para que caracteres especiales como acentos, espacios o emojis viajen sin perderse en la petición HTTP.

Cómo se reciben mensajes nuevos cada tres segundos

Una segunda función ejecuta una petición de lectura del mensaje más reciente cada 3000 milisegundos. Si recibe vacío, no hace nada; si recibe contenido, lo decodifica de URI a texto legible y lo agrega con addMessage pasando false, marcándolo como entrante [05:45].

Esa frecuencia de tres segundos genera la sensación de tiempo real sin saturar la radio LoRa con peticiones constantes.

Cómo se ve el resultado en dos tarjetas conectadas

Al abrir las dos IPs de las tarjetas en pestañas distintas del navegador, ambas aplicaciones funcionan en paralelo. En la segunda pestaña basta con cambiar el color primary por el secundario para distinguirlas durante la prueba.

En la pestaña de network del navegador puedes observar cómo las peticiones cada tres segundos llegan vacías hasta que aparece un JSON con el mensaje, por ejemplo Hello, que se agrega a la pantalla. La otra tarjeta responde con World y la primera lo recibe casi al instante [07:30].

Con esto cierras un proyecto que combina pantalla OLED, comunicación LoRa por radio y una interfaz web moderna. Comparte en la comunidad tu propia versión del sistema de mensajería y cuéntame qué cambios harías al CSS o a la frecuencia de polling para adaptarlo a tu caso de uso.