Quizolai represents the most ambitious and extensive project I've undertaken on a personal level. What began as a mere hobbyist coding venture quickly evolved into a project to which I've devoted considerable time, effort, and passion. Quizolai has been a playground for experimentation with numerous technologies, and through this blog series, I aim to delve deeper into the architecture and developmental milestones that define it.
Backend and Platform
At the heart of Quizolai's backend is Nest.js, a comprehensive backend framework for Node.js that adopts a "batteries-included" approach, offering a more opinionated structure compared to libraries like Express, which it uses under the hood. This framework favors the development of clean code and maintains project structure clarity, especially as the project scales. Its module structure is reminiscent of Angular, providing a robust CLI akin to this framework, and draws parallels to Java backend frameworks like Spring Boot or Java EE, notably through its extensive use of annotations. Given that performance trade-offs were a secondary concern for Quizolai, the choice was relatively open. My desire to leverage TypeScript and deepen my knowledge in the Node.js backend ecosystem naturally led me to choose Nest.
Initially, Quizolai utilized SQLite for its database needs, simplifying setup during the early stages of development. However, due to performance considerations, a transition to PostgreSQL was made later. To interact with the database from the backend, Quizolai employs Kysely. It was crucial for me to stay close to direct SQL queries without resorting to a full ORM, balancing flexibility and the opportunity to enhance my SQL skills. Kysely strikes this balance well, mirroring SQL functionalities closely while ensuring type safety within queries. However, being relatively new, Kysely's documentation is not the most comprehensive, occasionally making work challenging. There were moments when working directly with SQL and a simple Node.js SQL driver seemed more appealing due to the potential complexity of Kysely queries.
For authentication, Quizolai uses Passport.js along with various strategies. In the past, I've typically outsourced authentication through OAuth and providers like Auth0 or Keycloak. However, eager to gain more experience in this area, I opted to develop Quizolai's auth flow using Passport.js. A priority was to store as little sensitive information as possible, leading me to choose magic link authentication as the sole login method. This decision provided an excellent opportunity to delve into security aspects such as JWTs, access and refresh token rotation, and the debate between cookies and local storage, substantially broadening my knowledge in these areas. This topic may warrant a dedicated blog post in the future.
Quizolai and its database are fully dockerized and hosted on a VPS Ubuntu Server. This decision stemmed primarily from my extensive experience with Homelab, seeing significant value in furthering my expertise in this area. I also enjoy exploring topics related to DevOps and infrastructure. Deepening my understanding of Docker, writing various Dockerfiles, and optimizing them for quick build times and efficiency have been particularly rewarding. The VPS employs numerous other tools, such as Nginx Proxy Manager for reverse proxying applications, Plausible Analytics as a privacy-conscious alternative to Google Analytics, Portainer for easier Docker container management, and Uptime Kuma for monitoring downtimes.
This project also marked my first in-depth engagement with CI/CD, utilizing GitHub Actions to streamline development processes.