Skip to content
Profile
E. Burgos
30 de septiembre de 2026Por Esteban Burgos7 min de lectura

DisplayAds: la arquitectura real detrás de un SaaS de cartelería digital que llega hasta el hardware

#SaaS#arquitectura de software#IoT#NestJS#Spec-Driven Development
DisplayAds: la arquitectura real detrás de un SaaS de cartelería digital que llega hasta el hardware

Soy Esteban Burgos, Forward Deployed Engineer, y durante los últimos meses construí DisplayAds, un SaaS de cartelería digital que hoy está en producción en displayads.com.ar. No es un prototipo ni un side project a medio camino: es un sistema completo que va desde el navegador hasta una Raspberry Pi conectada a una pantalla en un local físico.

Escribo este post porque creo que hay poca literatura honesta sobre cómo se construye un producto que cruza la frontera entre software y hardware cuando el equipo es una sola persona. Acá va el recorrido completo, con lo que hace el producto, las decisiones de arquitectura, las tecnologías y cómo mantuve el orden en un proyecto que terminó teniendo 41 modelos de datos, 31 controllers, 117 specs de Spec-Driven Development y más de 680 archivos de tests.

Las 8 piezas que componen DisplayAds

Cuando alguien me pregunta "¿qué es DisplayAds?", la respuesta corta es "cartelería digital". La respuesta larga son ocho piezas que tienen que coordinarse sin fallar:

  1. API NestJS en tiempo real: el núcleo del sistema. Gestiona autenticación, contenidos, programación de reproducción y comunicación bidireccional con los dispositivos. Con 41 modelos de datos y 31 controllers, es la pieza más pesada del stack, y la que más pruebas concentra.
  2. Webapp: la interfaz donde los clientes suben contenido, organizan playlists y configuran pantallas.
  3. Backoffice: el panel interno para operar el negocio: soporte, monitoreo de dispositivos, gestión de cuentas y billing.
  4. Landing: la puerta de entrada comercial, hoy visible en displayads.com.ar.
  5. Docs: documentación técnica pensada tanto para el equipo interno como para integraciones futuras.
  6. Agente en Raspberry Pi: el software que corre físicamente en cada pantalla.
  7. App Android: una alternativa de hardware para clientes que ya tienen una Smart TV o un dispositivo Android en lugar de una Raspberry Pi.
  8. Pipeline de despliegue y observabilidad: la capa que conecta todo lo anterior y que permite lanzar cambios sin romper dispositivos que están funcionando, sin supervisión, en un local a cientos de kilómetros.

Ninguna de estas piezas es opcional. Si el backoffice falla, no hay soporte. Si el agente falla, hay una pantalla negra en un comercio real. Diseñar esto como ocho sistemas separados pero coordinados fue la decisión de arquitectura más importante del proyecto.

El dispositivo: reproducción offline con caché local

Una pantalla de cartelería digital no puede depender de que la conexión a internet del local esté siempre disponible. Los routers se reinician, los proveedores de internet fallan, y nada de eso puede traducirse en una pantalla negra frente a un cliente.

Por eso el agente que corre en cada Raspberry Pi 5 está escrito en Python y resuelve la reproducción con dos piezas clave: mpv como motor de reproducción de video y SQLite como caché local. El dispositivo descarga el contenido programado con anticipación, lo guarda localmente, y reproduce desde esa caché sin depender de que la API esté accesible en el momento exacto de la reproducción. La conexión a internet se usa para sincronizar contenido nuevo y reportar estado, no para reproducir.

La app Android, escrita en Kotlin, sigue el mismo principio pero corre en modo kiosco: la pantalla queda bloqueada en la aplicación de DisplayAds, sin acceso al resto del sistema operativo, algo imprescindible cuando el dispositivo está en un espacio público sin supervisión técnica.

Este patrón —offline-first en el edge, con sincronización oportunista— es probablemente la decisión que más tiempo de diseño se llevó, porque cualquier error ahí se ve directamente en una pantalla física, y no hay logs de consola para debuggear en el momento.

Actualizaciones remotas con rollback autónomo

La segunda decisión difícil fue: ¿cómo actualizo software que corre en un dispositivo físico sin acceso remoto directo garantizado y sin que un error de despliegue deje la pantalla inutilizable?

La respuesta fue construir un sistema de actualizaciones remotas donde cada dispositivo valida la nueva versión antes de comprometerse con ella. Si la actualización no pasa las validaciones esperadas en el propio hardware, el dispositivo revierte automáticamente a la versión anterior conocida como estable, sin intervención humana. Esto se validó en hardware real, no en un entorno simulado, porque las fallas típicas de un dispositivo embebido (cortes de energía en medio de una escritura, memoria SD degradada, reinicios inesperados) sólo aparecen cuando el software corre en las condiciones reales del campo.

Para un CTO evaluando construir algo similar, esta es probablemente la pieza que más subestiman al principio: el costo de una actualización remota mal diseñada no es un bug, es una flota de dispositivos ladrillo que hay que visitar físicamente uno por uno.

Las tecnologías detrás de cada pieza

Cada pieza usa la herramienta que mejor resuelve su problema, dentro de un monorepo Nx con pnpm que las mantiene coordinadas:

  • API: NestJS 11 con REST y WebSocket, Prisma sobre PostgreSQL 16 con pgvector, Redis con Bull para las colas y Socket.io con adaptador Redis para la comunicación en tiempo real con los dispositivos.
  • Webapp y backoffice: React 19.
  • Landing: Next.js con renderizado del lado del servidor.
  • Agente del dispositivo: Python en Raspberry Pi 5, con mpv controlado por IPC y SQLite para operar sin conexión.
  • App Android: Kotlin en modo kiosco (Device Owner).
  • IA: Gemini como proveedor principal con fallback a OpenRouter, y un motor RAG propio sobre pgvector que reutilizan la landing, la documentación y el agente operativo.
  • Entrega continua: 8 workflows de CI/CD que despliegan la API, la landing y los frontends, ingestan la documentación en el RAG, publican la app Android y validan el proceso SDD.

Ninguna tecnología está por moda: cada una resuelve una restricción concreta del producto, desde la reproducción sin conexión hasta la comunicación en tiempo real con toda la flota.

Cómo Spec-Driven Development ordenó 117 specs en un producto de una sola persona

La pregunta que más me hacen otros tech leads cuando ven la complejidad de DisplayAds es: "¿cómo mantenés esto ordenado si sos una sola persona?". La respuesta es Spec-Driven Development (SDD).

En lugar de escribir código y documentar después —o peor, no documentar nunca—, cada pieza de funcionalidad relevante del sistema se especifica antes de implementarse: qué problema resuelve, qué contratos expone, qué casos límite tiene que cubrir. En DisplayAds esto se tradujo en 117 specs que ordenan las 8 piezas del sistema, sus 41 modelos de datos y sus 31 controllers, y que sirven como la fuente de verdad cuando hay que tocar código escrito hace semanas sin tener todo el contexto fresco en la cabeza.

Esa disciplina también es la razón por la que el proyecto llegó a tener más de 680 archivos de tests: cada spec define comportamiento esperado, y ese comportamiento esperado se convierte naturalmente en casos de test. No es cobertura por cobertura, es cobertura que nace de haber pensado el problema antes de escribir la solución.

Cada ciclo de SDD además registra cuánto consume cada agente de IA: modelo, nivel de esfuerzo y tokens de entrada y salida. Con esa telemetría de costos sé cuánto costó construir cada funcionalidad y dónde conviene usar un modelo más económico sin bajar la calidad. En DisplayAds son 117 specs y 104 ciclos con esa trazabilidad.

Para un equipo de una persona, SDD no es un lujo metodológico: es lo que permite construir con la misma rigurosidad que un equipo de diez, sin sacrificar velocidad ni perder el hilo cuando el sistema crece.

Cierre

DisplayAds es un ejemplo concreto de que se puede construir un producto que cruza software y hardware, con la seriedad de un proyecto de equipo, sin sacrificar calidad por velocidad. Arquitectura clara, offline-first en el dispositivo, actualizaciones remotas confiables, tecnologías elegidas por restricciones reales y un método que ordena la complejidad en vez de esconderla.

Si estás evaluando construir algo parecido —un producto con dispositivos físicos, una API en tiempo real, o simplemente necesitás poner orden en un proyecto que está creciendo más rápido de lo que tu equipo puede documentar— te invito a visitar https://estebanburgos.com.ar/servicios y conversemos sobre tu caso.

Escrito por Esteban Burgos
ESTEBAN BURGOS

Sobre el autor

ESTEBAN BURGOS · Forward Deployed Engineer

Construyo software de punta a punta para pymes y empresas: webs, plataformas y soluciones con IA. Escribo sobre lo que aprendo en proyectos reales.

Conocé mi trayectoria

¿Querés algo así en tu empresa?

Contale tu idea a Tuki y en minutos tenés un rango de precio en tu moneda.

Seguí leyendo

Comentarios

Sé el primero en comentar.