2024

Dungeoneer

Dungeoneer is a project meant to keep track of what collectibles you are missing from dungeons, trials or raids in the game Final Fantasy XIV. You can either store your collection locally or log in and store it on your account.


Technologies and Tools

  • Next.js

    Next.js was chosen as the framework for the project due to its simplicity, ease of use and industry-wide adoption. Furthermore, we knew large parts of the project could benefit from server-side rendering, which Next.js excels at.

    We opted for using the more modern Next.js App Router, and in 2025 we switched from tRPC to a mix of Server Actions and API Routes.

  • Redis

    The project contains large datasets that are accessed frequently, such as item or instance lists, therefore we integrated Redis to optimize performance by caching them. This reduced database load and significantly improved response times for read-heavy operations.

  • Auth.js

    One of the main features of the project is the ability to log in and store your collection on your account. To achieve this, we used Auth.js, which provides a simple and secure way to handle user authentication and authorization.

  • Cheerio

    Scrapping “The Lodestone”, Final Fantasy XIV’s website, for information is a very common task in the project. We often need to search for characters, or for the specific information about a character’s collection of items. To achieve this, we used Cheerio, a fast and flexible HTML parsing library, which allowed us to easily scrape the website.

  • TailwindCSS + Motion

    Tailwind provided us with a fast and reliable way to style the project. However, we wanted to add some animations to certain elements, and we used Motion (formerly Framer Motion) to achieve this.

  • Supabase

    Supabase is a cloud-based database that provides a robust and scalable solution for storing and retrieving data. We used it to store the in-game data, the user’s collection and information, and to handle user authentication. Furthermore, we use Supabase Buckets to store the images of the items.

  • Vercel

    Since we decided on using Next.js, deploying to Vercel seemed like the best, most efficient option. We utilized Vercel’s Analytics and Speed Insights to ensure the project was running smoothly.

  • tRPC Deprecated

    We expected the project to have a lot of API calls and complex types of data, so we decided to use tRPC to handle the communication between the client and the server to ensure typesafety and a faster, safer development.

    In 2025, we deprecated tRPC in favor of a combination of Server Actions and API Routes, leveraging native Next.js features, edge functions, and Redis-based caching for improved performance and maintainability.


Roles and Responsibilities

This project was first developed by a team of three developers in 2022. However, it was eventually abandoned and I took over the project in 2024 as its sole developer.

  • UI/UX Designer

    Designed the user interface and user experience of the project. I used Figma to create the designs and implemented them in the project using TailwindCSS and Motion.

  • Full-Stack Developer

    Implemented the project’s functionality and ensuring it was secure and scalable. I used Next.js, tRPC, Auth.js, and Supabase amongst other tools to build the project. Later on, I also used Redis to optimize the data fetching process, server actions to handle mutations, and Cheerio to scrape the Lodestone.

  • Project Manager

    As the sole developer, I was responsible for its overall management and maintenance. I ensured the project stayed on track, with a focus on core features and bug fixes, without letting feature-creep distort the project’s direction.


Challenges and Solutions

  • Project Overhaul

    Once I took over as the sole developer, I knew two things: the project was unfinished, and the technologies used were outdated. In this initial state, it used a simple Angular + MongoDB stack. I decided to use Next.js and switch to PostgreSQL, as they seemed to be a better fit for the project’s requirements.

    In regard to the frontend, the switch was relatively smooth. The initial frontend was not complex, and replicating it in Next.js was somewhat straightforward. However, I had to rewrite the entire backend from scratch. The database was completely different, as was the API and the authentication system.

    In the end, I think this complete overhaul was a good decision that has led to a more robust and scalable project, with a faster development cycle.

  • UI Clutter

    One issue I faced while building the UI was clutter. There were too many elements on the page, and the layout was not intuitive. At the same time, I wanted to keep a clear navigation structure, so users could easily find what they were looking for.

    I decided to simplify the UI: the navigation menu would consist of a few buttons linking to the main sections, and a dropdown for other sections and options such as login and theme switching.

    Similarly, item cards were also simplified. Instead of the text writing out what type of item it was, or where it came from, I decided to use icons to represent this, and use dropdowns to show the item’s details.

    Overall, while there is room for improvement, I believe the current design is a good balance between functionality and visual clarity.

  • Data Fetching & Virtualization

    As mentioned earlier, the project contains large datasets that are accessed frequently, such as item or instance lists. This, if not handled correctly, could lead to performance issues and slow response times.

    To address this, initially I implemented a scroll-based fetching strategy, where the user would scroll through the list of items, and the items would be fetched in batches. This worked well and the data was fetched and loaded quickly. However, the performance greatly degraded as the user scrolled further down the list.

    To improve performance, I implemented a virtualized list component that rendered only the visible items. This allowed for a smoother user experience, as the user would only see the items that were visible on the screen, and the data would be fetched only when needed.

  • Data Acquisition

    Initially, the project was dependent on XIVAPI’s Lodestone functions to search for characters and their collections. However, they became deprecated after XIVAPI v2, and the alternative APIs and libraries were not as well-suited for the project’s needs.

    The Lodestone is a notoriously difficult website to scrape, and this was my first time attempting such a large scope of scraping, but thanks to the community’s help, I managed to implement Cheerio to scrape the website and extract the necessary data. With that, I did a complete overhaul of the Lodestone-related functions, such as character search and collection retrieval.

    The end result is a more robust and reliable system, without unnecessary middlemen or external dependencies.