Lo que no se lee en los medios

Chema Roldán
Genially Tech
Published in
12 min readJun 9, 2021

--

Puede ser que últimamente hayas oído hablar de Genially en algún medio de comunicación, ya sea en algún medio digital o incluso en televisión. En cada una de las entrevistas que nos han realizado hemos contado nuestra historia como startup y en cómo nos hemos convertido en un estándar para la creación de contenidos interactivos. Pero hay una historia que nunca hemos llegado a contar. Como creadores de un producto digital tenemos una historia de retos tecnológicos superados y que tenemos que afrontar, una historia de creación y evolución de nuestra base de código. Una historia que también merece ser contada, y que de hecho os vamos a contar.

Una de las cosas que más sorprende, aunque no lo creáis, es que en Genially no hay nada en producción de lo que se hizo durante los dos primeros años. Si hacemos una pequeña reflexión, el motivo de que no quede nada de ese código es que en Genially siempre se ha tenido como objetivo la mejora constante, y este mantra se refleja claramente en nuestro departamento de tecnología.

Un poco de historia sobre nuestro stack

La primera versión que salió a producción fue desarrollada con ASP.NET 4.5 y jQuery. Nos sirvió para validar el modelo de negocio y, sinceramente, era la tecnología con la que más cómodo me encontraba y con la que me veía capaz de sacar la primera beta a producción. A día de hoy, nuestro stack ha cambiado mucho y ahora todo está hecho con Javascript: Node.js en el backend, junto con TypeScript y siguiendo los principios de Domain-Driven Design (DDD), y React en el frontend. Eso sí, aunque seguimos usando MongoDB como base de datos, ahora también trabajamos con PostgreSQL y toda nuestra infraestructura se despliega en AWS.

Todos estos cambios no han sido por casualidad o por modas. Nuestro sistema iba a necesitar escalar muchísimo y en este contexto Node.js era lo ideal para gestionar las millones de peticiones que estimamos que tendría nuestro backend. En el frontend, jQuery empezaba a dar señales de que no podía escalar lo suficiente y que tendríamos que virar hacia un código donde pudieran tocar decenas de manos a la vez. Y así fue cómo entró en escena React. Pero no solo React, debido a la naturaleza de nuestro producto, teníamos que manejar el estado global de la aplicación de una forma particular, y fue por lo que tomamos como decisión el usar MobX, en concreto MobX-State-Tree, como gestor de estado. Aunque por aquel entonces todo el mundo usaba Redux, no nos dejamos llevar porque fuera el más usado. Esto último creo que ha sido una de las mejores decisiones del equipo y una pieza clave en nuestra arquitectura.

Un sinfín de retos cumplidos y por cumplir

Cuando me preguntan en los medios qué es lo que más me gusta de mi trabajo yo siempre contesto lo mismo: los retos. Genially nos ha estado retando cada día. Nos ha retado a resolver problemas que no vienen en los libros. Nos ha retado a cumplir el objetivo de ser un estándar en la creación de contenidos. A día de hoy, estamos en el buen camino. Pero lo mejor de todo esto, es que aún tenemos nuevos retos que resolver. Particularmente, tengo la suerte de trabajar cada día con un equipo increíble de ingenieras e ingenieros, personas maravillosas de las cuales aprendo cada día algo nuevo. Que adoran lo que hacen y que tienen, desde mi humilde opinión, la misma motivación que tengo yo en mi día a día.

No es fácil, y a veces te falta tiempo para explicarlo, pero en este caso intentaré hablar de algunos retos que hemos resuelto y algunos que nos quedan por resolver. No voy a usar un orden cronológico, simplemente voy a contar los retos que me han parecido más interesantes y bonitos.

Los textos, el font picker y el color picker

Todos hemos usado alguna vez el típico editor WYSIWYG. Un infierno. Ninguno va bien o tan bien como tú quieres que vaya. Nosotros tuvimos que hacer nuestros propios textos. Los primeros textos que se usaban en Genially, usaban un CkEditor (un plugin de jQuery). Ahora ya no. Tenemos unos textos que son capaces de trabajar sobre un contenido editable en tiempo real, donde usando las APIs de los navegadores somos capaces de utilizar cualquier tipo de comando (poner negrita, subrayado, cambio de color, etc.). Pero, ¡sorpresa! las APIs no funcionan igual en todos los navegadores, y el reto de hacer que esto funcionase como nosotros queríamos y de forma homogénea fue brutal. Cuando tienes unos textos que funcionan tan bien, necesitas acompañarlos de un font picker que funcione igual de bien. Para la primera versión usamos un componente con jQuery que nos permitía usar las fuentes de Google Fonts. Estábamos limitados a la hora de añadir o quitar fuentes que desde nuestro equipo de producto las veían necesarias. Nos hicimos el nuestro propio, y ahora somos capaces de integrar cualquier fuente de Google Fonts o las que se quiera en un abrir y cerrar de ojos. Lo mismo nos pasó con el color picker. Usamos el típico componente open source de React pero se nos quedaba corto así que, tras varios parches, nos vimos en la misma tesitura: necesitábamos crear el nuestro propio desde cero para que funcionase exactamente como queríamos. Además, estos dos componentes los hicimos con una intención: hacerlos open source. Pero es verdad que, por falta de tiempo, aún no hemos podido llevarlo a cabo. Necesitamos más manos para poder devolver a la comunidad todo aquello que nos ha proporcionado.

Textos, font picker y color picker

El crop: recorta tus imágenes en tiempo real

Este reto también es digno de contar. Antiguamente en Genially, cada vez que se recortaba una imagen, se generaba una nueva en base64 que acababa convirtiéndose en una URL en nuestros buckets de S3. No funcionaba como queríamos y tenía algunos pain points: como por ejemplo guardar y mantener la versión original de la imagen o cargar esas imágenes en memoria para poder acceder a ellas a través de un canvas de HTML. Cambiamos cómo funcionaba todo y comenzamos a trabajar con las propiedades de CSS inset, lo que nos permitía un recorte más rápido y eficaz. Además rehicimos el módulo de trigonometría para que el recorte de imágenes giradas fuese mejor, ya que posicionar los elementos recortados exactamente como tú los ves en el lienzo no es algo fácil y queríamos que funcionara perfectamente.

Recorte de una imagen en tiempo real

Las gráficas y tablas

Cuando tu producto se encarga de generar contenidos que comuniquen mejor y sean más efectivos y atractivos, te obliga a añadir algo tan “básico” como unas gráficas. Básico sí, pero complejo. Aquí sí nos apoyamos en una librería de gráficas open source para desarrollarlas, aunque también es verdad que hicimos algunas por nuestra cuenta porque no nos gustaba el resultado. Además, al poco se añadió la opción de poder crear tablas ya que nuestros usuarios del sector corporativo necesitaban poder crear este tipo de recursos. Para todo el equipo fue todo un éxito el desarrollo de esta nueva funcionalidad y pudimos abordarla en varias fases. La primera versión la tuvimos en un mes, pero luego se fue iterando poco a poco para mejorar todo el sistema. Y ya de paso aprovechamos para refactorizar el sistema de creación de nuevos elementos para nuestro editor, para que a la hora de crear nuevos elementos, todo fuera más rápido y mejor.

Edición de una gráfica

Teams

Los tiempos han cambiado, ahora mismo el uso grupal de las herramientas es un must. Aunque esto puede parecer fácil, ha sido uno de los retos más complejos de llevar a cabo, hemos tenido que crear carpetas colaborativas, permitir añadir colaboradores a esas carpetas, crear espacios de trabajo, gestión de roles, etc. Las posibilidades o caminos posibles eran y son muy complejos. Puede ser la feature más “subestimada” en su desarrollo… y eso que hemos hecho todo lo posible para que fuera lo más fácil posible de llevar a cabo. Incluso llegamos a hacer un POC a nivel interno, sin ningún tipo de backend, para validar todo el funcionamiento del sistema de carpetas, roles y colaboraciones. Hacer algo tipo Google Drive o Dropbox no es sencillo, os lo decimos de verdad. Ya lo tenemos en la fase final de su desarrollo y la verdad es que hemos aprendido muchísimo por el camino. Además, hay que añadir el reto de la gestión de pagos grupales o por asientos. Otro reto que nos ha obligado a estrujarnos el cerebro al máximo para que, cuando salga a producción, sea todo un éxito.

Importante aquí es destacar el cambio de paradigma que hicimos hace un par de años. Hicimos una gran apuesta pasando de una API enfocada puramente a REST que se parecía mucho a una Database-as-a-Service, a una API basada en una arquitectura enfocada al dominio con DDD. Si no hubiera sido por este cambio, no hubiéramos podido llevar a cabo este reto. He de reconocer que es todo un orgullo ver cómo todas las personas que se incorporan a la parte de backend son productivas en muy pocos días. Esto no hace otra cosa que confirmar que nuestra arquitectura tiene unos buenos cimientos.

Versión beta del workspace de un equipo

La comunidad

Nuestros usuarios crean contenido. ¿Por qué no aprovechar todo ese contenido ya creado para que lo puedan disfrutar otros usuarios? Pues nos pusimos manos a la obra en crear las bases de lo que conocemos como “comunidad”. Lo primero que desarrollamos fue la funcionalidad de poder reutilizar un genially siempre y cuando el usuario lo marcara como “reutilizable”. Otro paso más fue la creación de un escaparate o perfil social donde el usuario pudiera mostrar todas las creaciones que quiere compartir con otros usuarios para que puedan verlas o incluso llegar a reutilizarlas. Como todo en Genially, esta parte ha sufrido una evolución en su implementación. Inicialmente la teníamos hecha “a la antigua usanza”, es decir, con una aplicación MVC en Express.js que usa Nunjucks como motor de renderización. Pero una vez más, necesitábamos que el código escalara mejor, así que decidimos aprovechar para explorar la opción de hacer Server Side Rendering (SSR) con React. Hicimos una prueba de concepto que fue muy exitosa, ya que los tiempos de respuesta de Nunjucks eran más lentos que los de React con SSR. Blanco y en botella. Reemplazamos todo el módulo de renderizado y cambiamos.

Perfil social

Colaborativo en caliente o real time

Esto va a ser sí o sí un artículo aparte, porque da para un libro. Hemos tenido que hacer un refactor del core del código de nuestro editor para permitir que varios usuarios trabajen a la vez sobre un mismo genially. Ya hemos cambiado todo y actualmente tenemos la parte del frontend resuelta… y hemos tardado menos tiempo del esperado en llevarlo a cabo. Si no hubiéramos usado MobX-State-Tree no podríamos haberlo ejecutado en tan poco tiempo. Su sistema de patches ha encajado perfectamente y, lo mejor de todo, es que ya venía out-of-the-box con este framework. Ni qué decir que incorporar a nuestro equipo al mayor contribuidor de código de este framework nos ha ayudado bastante, la verdad. Ahora nos queda por resolver la parte de la infraestructura y está siendo realmente divertido. Hemos tenido varias sesiones y estamos probando diferentes opciones. A día de hoy ya tenemos claro cómo vamos a comunicar estos mensajes entre los diferentes clientes. Nos vamos a basar en un sistema stateless, concretamente vamos a usar API Gateway, Lambda y DynamoDB, ya que consideramos que es lo que mejor escala al no depender de servidores. Continuará porque esto no ha hecho más que comenzar.

Versión en desarrollo del colaborativo en caliente

El nuevo “autorizador”

La seguridad es muy importante en Genially. Hay pocas piezas más importantes que el darle acceso a nuestro sistema a un usuario. Llevábamos tiempo con toda la parte de login y registro acoplada a la web. Era algo que no nos gustaba. Hemos aprovechado que estamos desarrollando nuestra nueva web basada en un CMS y Gatsby. Esto nos va a permitir distribuir nuestra web a través de un CDN y hacerla más escalable. Y lo más importante, vamos a poder darle independencia al departamento de marketing y contenidos para que puedan generar los contenidos sin mediar el departamento de tecnología. Y qué mejor momento para extraer toda la lógica de login, registro, reseteo de password, etc. a un nuevo servicio independiente que nos permita integrar incluso otros sistemas de acceso, como pueden ser un JWT (pensando en los dispositivos móviles), un OAuth, un Active Directory o cualquier otro sistema de Single Sign-On. Además, como la prueba de la comunidad usando SSR había sido un éxito, todo este sistema se ha hecho usando la misma tecnología. Va más rápido, es más escalable, el código es mejor, hemos aprovechado para actualizar dependencias y, en líneas generales, es para todo el equipo un claro ejemplo de éxito y de cómo desacoplar una pieza tan importante.

De CircleCI a Jenkins

En Genially el Continuous Delivery es muy importante, que algo llegue a producción lo antes posible es parte de nuestro objetivo. Con nuestra antigua CI, CircleCI, estábamos cómodos cuando trabajamos con los típicos entornos de producción, staging y development. Pero ya se nos habían quedado cortos. Así que nuestro equipo de DevSecOps migró todos nuestros workflows de CircleCI a Jenkins porque no podíamos hacer todo lo que queríamos, que no era otra cosa que montar lo que hoy en día conocemos en el equipo como “los entornos dinámicos”.

Los “entornos dinámicos” son entornos de preproducción que se crean “al vuelo” cuando se hace un pull request (PR). Me explico. Cuando un desarrollador o desarrolladora hace un PR, con una Github Action se añaden las etiquetas correspondientes para saber qué módulo se ha modificado. Si añades una etiqueta específica llamada “build”, nuestra CI va a crear automáticamente un entorno exactamente igual a lo que hay en producción, pero incluyendo tus modificaciones de código solo en aquellos módulos que el sistema ha detectado que han cambiado. La CI crea tanto las bases de datos desde cero con unos datos precargados, las APIs, aplicaciones… absolutamente todo ¡y en menos de 10 minutos! La magia que hay tras esto no es otra cosa que Kubernetes.

Esto es lo que nos ha permitido que se puedan hacer, entre otras cosas, tests automáticos end-to-end sobre un entorno de preproducción para que puedan validar que no se “rompe” nada y, como hemos dicho antes, que nuestro código llegue a producción lo antes posible. Una maravilla que en nuestro día a día ya tenemos interiorizada pero que nos da una agilidad descomunal.

Vista de uno de nuestros workflows en Jenkins

Creando un departamento de QA

Genially tiene que funcionar bien sí o sí. Pero además tiene que funcionar igual de bien en Chrome, Firefox, Safari y Edge, además de en tablets y demás dispositivos móviles. Hasta hace un año nuestro proceso de QA se basaba en tests unitarios y de integración automáticos, que se complementaban con un proceso de pruebas manuales. Todo esto ha cambiado y hemos pasado a usar Cypress para implementar un sistema de testing automatizado que nos asegure que todo funciona como debería. Hemos pasado, en muy poco tiempo, de no tener nada a tener ya más de 332 tests, los cuales tardan en ejecutarse tan solo 1 hora y 15 minutos si lanzamos la suite completa, y entre 10 y 25 minutos si hablamos de la suite básica. Es tan bueno lo que hemos montado que cuando hemos hablado con el equipo de Cypress para tratar ciertos aspectos de optimización, nos han pedido que hagamos un artículo (actualmente en desarrollo) para contar cómo hemos implementado todo nuestro sistema, especialmente el sistema de paralelización de los tests que nos ha permitido reducir los tiempos de ejecución en más de la mitad.

Histórico de resultados de la ejecución de la suite completa de tests

Futuros retos

Hemos contado algunos (hay muchos más) de los retos que hemos ido superando estos años, pero tenemos otros retos muy bonitos que resolver ahora y en los próximos años. No os imagináis lo que te hace crecer, aprender y disfrutar cuando los resuelves y acaban en producción en mano de nuestros usuarios. Tenemos una especial ilusión con algunos de ellos porque sentimos que hemos hecho, todas y todos, un gran trabajo y con mucho cariño. Para mí, personalmente, es algo que no tiene precio.

Buscamos talento

Si has llegado hasta aquí y te ha gustado lo que has leído, nos gustaría que te unieras a nuestro equipo para ayudarnos a resolver y llevar a cabo los nuevos retos que tenemos por delante y que incluso ahora mismo ni imaginamos. Si crees que puedes aportar a esta gran familia, estaremos encantados de recibirte con los brazos abiertos. Puedes contactar conmigo en mi twitter (Chema Roldán), tengo los mensajes abiertos o si prefieres por correo a tech@genial.ly.

Muchas gracias por leernos. Feliz día.

Este post está dedicado a todos los equipos que forman Genially. Desde desarrollo, producto, marketing, data, customer success, financiero, legal, ventas y operaciones. Sin todos vosotros y vosotras no podríamos estar haciendo este sueño realidad.

--

--