Motos y tecnología, unidos con Supabase
La mayoría de los developers ha pensado en crear una herramienta para usarla en algo que nos apasiona. Algunos lo hemos hecho realidad.
A lo largo de mis 12 años como profesionista he comenzado por lo menos 12 aplicaciones con esta naturaleza. Al inicio de cada una, hay un hype muy intenso, pero paulatinamente disminuye hasta abandonar el proyecto. ¿Suena familiar? En este artículo, te hablaré de cómo finalmente logré esta meta con un app hecha desde cero, vinculada con lo que me gusta y hasta con ganancias: NorthBikers.
Durante los últimos 3 años, -casi- cada fin de semana he visitado con distintos grupos de motociclistas a visitar lugares muy remotos, con rutas de terracería, como se conocen comúnmente. Desde hace un año he sido el capitán de la ruta. En pocas palabras: soy quien la planea, convoca, dirige y quien cuida del grupo a lo largo del trayecto.
¿Y adivina qué? Como tantas veces en el pasado, pensé en mejorar mi experiencia en esta actividad que me apasiona a través de un app.
NorthBikers: Fase 1
Al inicio, la necesidad era muy básica: Tener checkpoints donde haríamos paradas para reagruparnos y que también funcionaran como puntos donde los compañeros que iban rezagados pudieran alcanzarnos.
Me considero un especialista en Angular, así que bastó un web app muy simple basada en este framework: Una lista de récords, donde cada uno constara de nombre, latitud y longitud de la ubicación.
Además de este frontend, necesitaba un lugar para guardar y consultar la información. En este punto, ya que el app era bastante simple, decidí explorar un backend as a service, ya que requería sólo una base de datos y API para consultarla, pero también quería tener la posibilidad de extenderla fácilmente en el futuro, si fuera necesario.
Tengo mucha experiencia con Firebase. Sin embargo, decidí explorar (y aprender) una tecnología/plataforma nueva: Supabase. Esta herramienta tiene servicios similares a Firebase, aunque la principal diferencia es que cuenta con una base de datos relacional (PostgreSQL) en lugar de una basada en documentos.
Cabe mencionar que Supabase provee una interfaz que permite manipular los datos de una manera sencilla. Así que decidí temporalmente insertar los récords de manera manual, en lugar de implementar funcionalidad extra en el app o un back office.
En este punto, la arquitectura es sumamente simple:
Plain & Simple: Un frontend conectado a una base de datos a través de las APIs que provee por defecto Supabase. Más adelante, verás que esta arquitectura se ha mantenido casi intacta.
Esto nos funcionó muy bien porque cumplió con su propósito de darnos una idea clara de los lugares de reagrupación.
No soy un gran fan de agregar componentes sociales a las apps solo porque sí. Un componente social debe cumplir un propósito. En este caso, debido al tipo de rutas que hacemos, es de GRAN ayuda saber quiénes van y cerciorarse de que cada uno de los participantes haya alcanzado los checkpoints. Si alguno no lo ha hecho, probablemente se perdió, pasó algo con su motocicleta o con él, en cuyo caso, hay que regresar a auxiliarlo.
Un componente social no siempre es como lo pintan. No necesariamente será un timeline lleno de fotos, videos y status de otras personas. Para un servidor, debe proveer una manera significativa de interactuar con los usuarios. En nuestro caso, el simple hecho de ver el check in de alguien más en un checkpoint fue más que suficiente(en ese momento).
La implementación fue sencilla:
- Habilitar componente de autenticación (Login, Registro, Perfil).
- Agregar nuevas tablas en la base de datos para guardar detalles de usuarios y de checkins en los checkpoints.
- En el frontend, permitir a los usuarios ingresar a un checkpoint y hacer su check in.
La arquitectura seguía siendo la misma, con la diferencia de que además de usar solo el módulo de database de Supabase, se comenzó a utilizar el de authentication.
Terminé con lo que puedo denominar un producto core, que cumple una tarea (o par de tareas) específicas y que por lo menos mi grupo y otros conocidos, querían y podían utilizar.
Claves para terminar bien
Aquí quiero contarte cuál fue la clave para llegar a esto: mantuve 👏🏽 las 👏🏽 cosas 👏🏽 simples 👏🏽.
Utilicé tecnologías que conocía o eran muy sencillas de usar, usé servicios gratuitos y agregué solo la funcionalidad que requería. Aun cuando tengo experiencia con servicios como AWS, Azure y he desarrollado backends desde cero con Node.js, C# y PHP, detecté y evité tratar de reinventar la rueda usando Supabase.
Dato curioso: a final de cuentas, Supabase hostea sus bases de datos en AWS.
Otro detalle que ayudó fue reprimir el impulso de usar React en el frontend. Sé que este comentario levantó más de una ceja, pero el motivo no es el que piensas: yo manejaba React a un nivel muy básico y estoy seguro de que implementarlo aquí me hubiera ayudado a conocerlo mucho mejor. Sin embargo, también estoy seguro de que me habría consumido más tiempo, llevándome tal vez a abandonar el proyecto, como en la mayoría de los casos.
Esto me permitió construir todo sin bloquearme por problemas técnicos y además me permitió no presionarme por costos mensuales de servidores o servicios.
NorthBikers: Fase 2
Lo construido en la Fase 1 era funcional y hasta cierto punto suficiente. No obstante, quise llevarlo al siguiente nivel.
Como lo mencioné al inicio, NorthBikers era, en su primera fase, una web app de Angular a la que se accede (por supuesto) a través del browser.
Aquí decidí analizar a mi audiencia. Aun siendo un grupo con rango de edades entre los 22 y 60 años de edad (o más), en su totalidad utilizaba su celular. Después de todo, ¿quién lleva su laptop a una ruta en moto? Bueno, a veces yo.
Entonces decidí mejorar la experiencia de usuario y, por lo menos desde el punto de vista de UX, que el app fuera más conveniente para todos.
Dado que el desarrollo se hizo en Angular y que, afortunadamente, soy muy flojo para actualizarme y desarrollar apps nativas para iOS y Android, opté por utilizar Ionic.
Simplificando, Ionic es Angular con estilos diseñados para móvil, integrándose muy fácilmente con librerías/frameworks como Cordova y Capacitor para acceder a los chips nativos.
Con esto en cuenta:
- Migré mi código de Angular hacia Ionic (reutilicé prácticamente el 100% de la lógica)
- Permití que el usuario suba una foto en los check ins . Esto es opcional, aunque muy utilizado actualmente.
- Además de seguir publicando el app en web, empaqueté el código para iOS y Android usando Capacitor y publiqué en sus respectivas tiendas.
Considerando la popularidad de la opción de subir foto junto con el check in, fue hasta cierto punto natural implementar un feed donde se muestran las fotos que suben otros usuarios. Esto fue experimental, pero gustó mucho: en el mundo del motociclismo, nos gusta mucho compartir nuestras experiencias. También se implementaron características como dar like, comentar y reportar fotos.
Aquí la arquitectura cambia un poco y, del lado de Supabase además de authentication y database, agregamos el uso de su servicio de storage.
En esta fase, hubo un nuevo feature que parece mínimo (sobre todo en el frontend):el cálculo de distancia entre un punto y otro.
Ojo aquí. Nadie me iba a decir: “Oye Eduardo, estaría muy bien que utilizaras el API de distance matrix para calcular la distancia entre puntos” 😅. Simplemente me topé muchas veces con la misma pregunta: ¿Cuánto falta para llegar a X? ¿Qué distancia hay entre Y y Z? Lo anterior a veces por curiosidad, por ansiedad o para saber si el combustible iba a ser suficiente para llegar.
Entonces decidí implementar ese feature. Al agregar/modificar los checkpoints, hago llamados al API de Google Distance Matrix para calcular la distancia entre puntos. Esto mejoró mucho la experiencia, así como ayudó a dar certidumbre y seguridad en la ruta.
Por ende, agregamos un nuevo elemento al backend en la arquitectura:
Claves para terminar bien
Ya tenía el core funcionando correctamente. En este punto, tuve que decidir entre dos alternativas:
- Dejar el app como estaba, es decir, funcionando bien, pero hasta cierto punto estancada.
- Extenderla y correr el peligro de hacerlo mal, tardar mucho o simplemente entregar algo que nadie usaría y entorpecer las funcionalidades core.
Varias veces he escuchado (y he dicho) la frase “Si jala, no le muevas”. Pero he encontrado que una manera de moverle y que no solo siga jalando, si no que jale mejor es analizando las necesidades de tu audiencia.
Hay que tener cuidado, sin embargo. Cuando preguntas a un usuario lo que quiere, difícilmente obtendrás una respuesta real sobre lo que en verdad necesita. En lugar de eso, analiza y usa tus conocimientos para obtener los mejores resultados.
Otro punto sumamente importante es que debes ser muy inteligente al elegir los features que vas a implementar, ya que algo tan simple como una etiqueta en texto que muestre la distancia entre dos puntos puede ser más útil que tratar de hacer una copia de TikTok o Facebook.
A todas éstas, ¿cuándo comencé a hacer dinero con mi app? Ya casi llegamos. Esto lo explico a continuación.
NorthBikers: Fase 3
En septiembre de 2021, participé en el Rally ADV NL. Este tipo de competencias generalmente tienen un track (o ruta) definido que debes completar. El lugar que obtendrás en la competencia dependerá del tiempo que te tome llegar a la meta.
El rally en el cual participé era diferente. Había un conjunto de lugares para visitar, distribuidos en todo el estado y cada uno con cierto puntaje (entre más lejos o difícil el lugar, mayor el puntaje). Este rally es de estrategia, aventura y turismo más que de velocidad.
[Video del rally en caso de que se desee incluir: Rally ADV NL 2021 - DOCUMENTAL COMPLETO]
La manera de comprobar que visitaste alguno de los puntos era tomarte una foto en él y, al terminar tu participación, subir todas las fotos a un Google Drive. Una vez terminado el periodo en el cual podías subir tu evidencia, un equipo de 15 personas localizado en la sede del evento analizaba todas las fotos subidas al Google Drive y asignaba el puntaje a cada una.
Mi amigo Joaquín Lam (el organizador del evento) me comentó que este proceso de calificación le tomó al equipo unas 6 horas muy intensas de trabajo.
¿Puedes adivinar adónde me dirijo con lo que estoy contando? Muy probablemente pensaste lo mismo que yo: es algo que puede ser automatizado y eficientar el proceso completo de calificación.
El primer paso para enfilar el app para realizar esta automatización fue complementarla con un dashboard donde Joaquín pudiera acceder y administrar su evento.
Ya que el tiempo era relativamente corto para implementarlo y aún tenía temas de evolución y bugfixing pendientes en el app, pedí ayuda a un colega (Miguel) para construir el dashboard. Miguel se especializa en React, así que lo usamos para hacer este desarrollo. La arquitectura quedó de esta manera:
Comencemos con las partes más obvias de implementar en esta tercera fase:
- En el app móvil, la acumulación de puntos a nivel de evento, a través de checkins.
- Captura de geolocalización al hacer check in.
- Captura de foto al hacer check in
- El sitio de admin, con autenticación simple, y una lista de participantes, actualizada en tiempo real con los puntajes de los participantes.
- De lo más importante: una sección de detalle por participante, donde el admin puede ver todos los checkins de cada participante, tener información de geolocalización, foto y distancia entre el lugar de check in y el checkpoint como tal.
Haciendo números, esta pantalla por sí sola ahorró unas 90 horas de trabajo de calificación de pilotos.
Aquí reitero: A veces algo simple aporta un gran valor a una aplicación. Solo dale un vistazo a esa pantalla, es básicamente una lista, un mapa y una foto. Nada complejo, pero sumamente útil.
Ahora pasemos a lo que representó un reto algo mayor, dado que nunca me había tocado implementar este tipo de funcionalidad en algún proyecto antes.
Verás, cuando haces rutas en lugares remotos, donde poca gente vive y son casi intransitables, generalmente no hay cobertura celular. Esto representaba un gran problema de cara a la operación del app durante la competencia, pues un gran número de checkpoints se encontraban en lugares de esta naturaleza.
Dada la existencia de las PWA y su soporte casi out of the box de funcionamiento offline, una parte del problema estaba cubierto que el app abriera y desplegara algo que no fuera el dinosaurio de Chrome.
Sin embargo, simplificando la arquitectura del app, se trata de un claro ejemplo de Cliente - Servidor, el cual necesita de internet para comunicarse.
Para maximizar la compatibilidad y, al mismo tiempo, mantener simplicidad en el app, usamos localStorage y la detección de conectividad a internet de navigator.onLine. Ambas APIs web nativas me ayudan a identificar si el navegador se encuentra offline y guardar la data en localStorage para luego enviar o recibir actualizaciones de los datos, una vez online.
Con esto finalizamos el desarrollo que permitió que Rally ADV NL en su edición 2022 y el Rally ADV Querétaro 2022 tuvieran un grado de automatización a nivel operación muy alto.
Considero a NorthBikers como una aplicación terminada y que probó su funcionamiento en producción, algo que con ningún otro proyecto había logrado.
¿Sabes qué otra detalle no había logrado? Monetizar una app propia. Anteriormente, había cobrado por desarrollos a la medida para pequeños y grandes clientes, de lo cual podría hablarte en otro artículo. Pero esta fue la primera vez que una idea mía se materializó y tuvo una culminación exitosa.
¿Cómo se monetizó esta aplicación?
- Indirectamente: Fue parte de un paquete de publicidad que ofrecí a mis patrocinadores,
- Directamente: En su modalidad de Software as a Service, su uso fue cobrado por evento,
Claves para terminar bien
La primera clave es analizar la operación, sobre todo aquélla que toma más tiempo hacer (ejemplo: El proceso de contabilización de puntos) e idear maneras de automatizarla a través del software.
Usar tecnologías y APIs sencillas (ej. APIs de localStorage y navigator) para lograr tu objetivo es también una manera de avanzar más rápido en el desarrollo. Usar tecnologías externas y más robustas requerirá frecuentemente de más tiempo invertido.
Esta fase 3 demandó una mayor cantidad de trabajo. Generalmente, estas etapas de detallado son las menos premiadoras ya que, como resultado, no se obtienen grandes avances visibles. La constancia y disciplina son factores muy importantes en este punto para no desistir y culminar exitosamente tu desarrollo.
Conclusión
Mantener todo simple al inicio, así como quedarte dentro de un core de funcionalidad (solo funcionalidad esencial) ayuda muchísimo a enfocarte en lo realmente importante, de modo que el desarrollo no se alargue de manera innecesaria.
Al identificar de manera eficiente las necesidades, una vez implementado el core, puedes identificar cómo los demás usan tu app y lo que pueden faltarle (o incluso sobrar). Lo más probable es que si preguntas cuál funcionalidad debería tener el app, lo que contesten no será lo que realmente necesitan. Pon atención a lo que gira alrededor de ella para identificar esos requerimientos.
Apretar el paso al final- Esto quizá sea lo más difícil de hacer cuando tus energías y el hype se han ido, cuando ya no hay nueva funcionalidad para implementar, así como cuando hay que pulir tu aplicación para que sea apta para uso en producción.
Combinar tu pasión y profesión no es algo sencillo, pero cuando funciona, es una de las mejores satisfacciones que puedes recibir en esta carrera.
Revelo Content Network da la bienvenida a todas las razas, etnias, nacionalidades, credos, géneros, orientaciones, puntos de vista e ideologías, siempre y cuando promuevan la diversidad, la equidad, la inclusión y el crecimiento profesional de los profesionales en tecnología.