Problema
Yula construía un producto de atención al cliente con IA para tiendas Shopify. Comportamiento del producto, simplificado: un email entrante de un cliente se categoriza, se busca contra una base de conocimiento extraída del sitio de la propia tienda, se redacta una respuesta, un segundo agente la autoverifica, y se envía o se reescribe (hasta tres intentos antes de abortar). El MVP necesitaba la superficie pública: landing, sign-up, selección de plan, configuración de tienda (dominio de negocio, firma de atención al cliente) y un preview “Generate an answer” donde los operadores podían probar el agente contra un email pegado antes de apuntarlo a su inbox real.
El backend no era trivial: un servicio FastAPI envolviendo un flujo de agente LangGraph, vector store Pinecone con namespace por tienda para multi-tenancy, colas en Redis con dead-letter queue y contadores de retry, integración con Gmail y auth con Clerk. Mi trabajo fue el frontend que hacía que todo eso se sintiera usable en tres meses sobre Heroku.
Enfoque
El producto tenía dos superficies en una sola base de código: una landing pública con funnel de sign-up en yula.ai, y una app embebida en Shopify donde los operadores de tienda configuran su dominio, firma y previsualizan corridas del agente desde adentro mismo del admin de Shopify. Construí ambas como un solo proyecto Remix — Remix es el stack que Shopify recomienda para apps embebidas vía @shopify/shopify-app-remix, y meter el sitio de marketing en el mismo proyecto significó un solo despliegue, un solo Prisma+Postgres para estado de tienda y manejo unificado de dos superficies de autenticación (Clerk para el funnel de sign-up off-Shopify; OAuth de Shopify en el lado embebido).
El frontend dividió su trabajo intencionalmente en tres capas:
- Los loaders de Remix (server-side, SSR) manejaron las lecturas SSR rápidas — auth con Clerk, estado de tienda desde Prisma — para que el dashboard renderizara hidratado.
- Una action de Remix (
/api/processEmail) se encargó de la escritura server-side breve — un upsert con Prisma que decidía si el contenido de la tienda necesitaba extraerse de nuevo — y devolvía en una sola respuesta rápida. - El componente React en el browser después orquestó el trabajo real de larga duración: llamaba directo a los endpoints
/scrapey/emaildel FastAPI y consultaba su estado cada cinco segundos en unwhileloop, todo en el browser.
La decisión no obvia de UI está en esa tercera capa: el botón que dispara la acción también es la superficie de estado en vivo. No hay spinner aparte, no hay barra de progreso, no hay toast — cuando el operador hace clic en Generate an answer, el texto del propio botón muta a lo largo del ciclo de vida de la tarea: On queue… → Collecting website content… → Writing the email for you… → Retrying… → Email ready. El control que apretaron se vuelve el indicador de lo que está pasando, lo que mantiene al dashboard en silencio mientras un agente multi-paso corre por debajo.
Me hice cargo del ciclo completo de despliegue del frontend en Heroku. Para un MVP que ya cargaba costo real de backend (vector store, llamadas a LLM, tier de Redis, manejo de dead-letter), mantener el ciclo de despliegue en minutos de un dígito significó iterar sobre la superficie que importaba para los sign-ups en vez de pelear con sobrecarga de plataforma.
Resultado
El sistema se construyó end-to-end y llegó a un MVP funcional — flujo del agente, retrieval RAG con namespaces por tienda, colas Redis con manejo de dead-letter, ruta de envío por Gmail y la superficie para operadores visible en la captura de arriba. El copy de la landing (“1 Month FREE, no card required”) es la historia de lanzamiento alrededor de la que construimos.
El producto nunca salió al público. El product owner terminó descontinuando la iniciativa por motivos de producto — el trabajo técnico estaba hecho. La arquitectura y el límite de integración que forzó — UI con sensación síncrona sobre un agente multi-paso basado en colas — es lo que vale la pena mostrar.
Estuve a cargo del stack de frontend end-to-end: Remix.js, Polaris + App Bridge, Clerk, Prisma y despliegue Heroku Docker. El backend — FastAPI envolviendo el agente LangGraph (categorize → RAG → draft → verify → send/rewrite loop), Pinecone con namespaces por tienda, cola + pub/sub + dead-letter de Redis con 3-retry, Gmail toolkit, OpenAI + Groq — era del equipo, y yo me integraba contra él.