Stop Rows es un sistema full-stack de gestión de colas remotas. El frontend incluye mapa interactivo, flujos autenticados para usuarios y dueños de tiendas, páginas SSR, infinite scroll, custom hooks, capas de servicios y componentes reutilizables. El backend fue migrado a TypeScript e incluye autenticación JWT con refresh tokens, RBAC, validación, manejo centralizado de errores, documentación Swagger, tests de integración, caché e índices geoespaciales en MongoDB.

  • preview
  • preview
  • preview
  • preview
  • preview
  • preview
  • preview
  • preview

Tecnologías implementadas

  • EXPRESS
  • MONGODB
  • MONGOOSE
  • SWAGGER
  • NEXTJS
  • REACT
  • TYPESCRIPT

Proceso y desafíos

  • Backend

    1. En primer lugar se estableció una estructura básica separando controllers, middlewares, services y routers. Decidí hacerlo de esta forma ya que la escalabilidad no es importante en este caso.

    2. Para poder crear los esquemas en mongoose, primero tuve que establecer una conexión y efectuar la configuración de Mongodb. Si bien no era la primera vez que usaba mongoose, esta vez quería documentarme mejor para poder aprovechar de una forma óptima las herramientas que Mongo ofrece. Por ejemplo, el uso de índices o atributos geoespaciales. Tuve ciertos problemas a la hora de hacer queries con ciertos filtros porque a día de hoy no tengo un entendimiento tan profundo de esta librería.

    3. En este paso se desarrolló la mayoría de la lógica de negocios. Tuve (y tengo) algunas dudas con respecto a ciertos aspectos de la arquitectura. Para solucionar este inconveniente leí un par de libros que explican cómo vertebrar una restful API (REST API Development with Node.js de Fernando Doglio y The REST API Design Handbook de George Reese).

    4. Aquí me centré en establecer un routing lo más intuitivo que pensé.

    5. Apliqué la validación de datos con JOI sabiendo que mongoose tiene una funcionalidad semejante. La decisión no tuvo ningún fundamento lógico más que me había quedado pendiente utilizar esta librería. Además, estructuré un middleware para el manejo de errores centrándome en los códigos de los errores que devolvía la base de datos y un 500 para los demás. Así, de esta forma no hay lugar a filtrar posible información sensible.

    6. Auth con passport middlewares particulares. Una funcionalidad importante para este proyecto es la autenticación y autorización. La autenticación fue resuelta con passportJS, utilizando las librerías de JWT y local. La autorización, en cambio, fue determinada por un sistema de roles y contrastando el id del usuario con el id del dueño del negocio.

    7. Algo muy importante que aprendí desarrollando este proyecto es sobre el Jest y la utilidad del testing: si bien no es la primera vez que ejecuto testing (en la universidad, cátedra paradigmas de la programación, era un requisito para entregar un trabajo práctico), es la primera vez que me es muy útil para detectar ciertos errores específicos que yo interactuando con Postman no encontraría. A futuro debería implementar los testeos en una etapa más temprana.

    8. Para el final dejé la documentación, no fue algo muy complejo pero no fue tan práctico como en el proyecto anterior. Utilicé Swagger nuevamente pero en este caso tuve que redactar las especificaciones manualmente. De todas formas el resultado fue óptimo.

    9. Deployment: en este caso me hice con la ventaja de un bono para utilizar en DigitalOcean. Por lo tanto, decidí albergar mi aplicación en esta PaaS. Fue algo simple: referencié el repositorio de GitHub, ingresé las variables de entorno y los comandos npm para efectuar el build y deploy a producción.

  • Frontend

    1. Primeramente desarrollé el esqueleto de la aplicación: una página para los usuarios nuevos o clientes y otro componente para que los dueños administren sus tiendas.

    2. Maps api, Recuerdo que para la secundaria tuve que usar la Google Maps API pero aplicado en html y js. Ahora en React puedo decir que es muy similar e intuitivo (además que está bien documentado).

    3. Posteriormente desarrollé un custom hook que consuma la API para hacer un infinite scroll utilizando interception observer. Fue interesante y útil de aprender.

    4. Hice una página particular para cada tienda. Esta recibe el id como parámetro de la url y busca la información desde el lado del servidor (SSP).

    5. Además elaboré un componente que mostrase la lista en “tiempo real” de clientes en la cola. Pudiéndose reciclar para los dueños, donde da la posibilidad de eliminar usuarios.

    6. En el aspecto de la autenticación, ya contaba con la experiencia de proyectos previos: alojando JWTs en cookies con una fecha de expiración, haciendo un custom hook para login, signup y logout. La principal diferencia es que en este proyecto implementé refresh tokens y tuve que aprender a manejarlos.

    7. Desarrollé un formulario reciclable para poder agregar y modificar tienda, lo que cambia entre ellos es la data que tiene de antes y las opciones del fetch.

    8. Mejoras de funcionalidades (borrar de lista, te aparece la lista en la pantalla principal, si fallaba el fetch no daba aviso).

    9. Este fue mi primer deploy de una aplicación hecha en NextJs. Había visto que en un curso de Platzi, hacían uso de un sitio llamado Vercel donde era muy rápido e intuitivo (además gratis). Ingresé mis credenciales y el deploy fue como lo prometieron.

Decisiones Técnicas

  • Índices geoespaciales en MongoDB

    Usé MongoDB con Mongoose para modelar los datos de colas y tiendas, incluyendo índices y atributos geoespaciales para dar soporte al mapa interactivo.

  • JWT con refresh tokens

    La autenticación usa PassportJS con estrategias JWT y local; la autorización es por roles, contrastando el ID del usuario con el ID del dueño de la tienda.

Desafíos

  • Incertidumbre de arquitectura

    Tuve dudas continuas sobre partes de la arquitectura de la REST API y las resolví leyendo libros dedicados al diseño de APIs a mitad de proyecto.

  • Aprendiendo filtros de queries en Mongoose

    Tuve problemas escribiendo ciertas queries de Mongoose con filtros específicos debido a un entendimiento incompleto de la librería en ese momento.

Estado Actual

Mantenido

Conclusión y mejoras a futuro

El caché fue implementado en el backend para optimizar los endpoints de mayor acceso. Las mejoras pendientes incluyen web sockets para ver las filas en tiempo real y mejoras en UX/UI como diseño responsive.