animatchup

designdevTypeScript

A website made to make rating your favourite anime easier.

Animatchup is a web application designed to let you competitively rate anime. The goal of the app was to solve a problem I had had with choosing which anime to rewatch, and a general pitfall of absolute scale ratings (i.e. 5 stars), which is to choose which one is “better” between two equally rated items. This project is build on TypeScript in two parts: the client is a NextJS application, designed with MUI, using Apollo client to retrieve and manage remote state, and OAuth2 through NextAuth to manage login and sessions. The backend is built on Apollo’s GraphQL server and Fastify’s HTTP server, using type-graphql to build the schema and resolvers, PostgreSQL to store data, Redis as a caching and rate limiting store, Prisma’s ORM to interface with the database, and Vite to build it all.

The project intially started as a Python TK gui simply for my own personal use, but after running into a number of roadblocks to UI design in Python, along with wanting to learn how to develop a website, I transitioned to building a web application for the project instead. The website has since undergone a number of rewrites as issues arose and new technologies appeared, having started with create-react-app and mercurius powering the front and back ends, to NextJS replacing create-react-app and Apollo replacing mercurius, and having changed hosts multiple times.

The architecture of the app is a bit complex but the idea is relatively straight forward. Conceptually, given a list of items, I would like to know which item is the best (and by proxy, where everything ranks). This is already a fairly explored area outside of shows, namely for video games and chess, using ELO/MMR systems. The goal of these systems is to place you on a leaderboard and determine where you rank relative to your peers. Such a system is typically represented as a statistical model, and the model chosen for this application is the Bradley-Terry model. Using this model, we can determine where on the list items rank based on how they fare in 1v1 paired matches. For example, I like item A more than item B and item B more than item C, and from these 2 matchups the model orders the list [A, B, C].

The construction of this app has taught me a great number of things. I learned (and am still learning) about security best practices regarding user information and login sessions; proper database structure and when to normalize vs denormalize data in a relational database; how to build complex APIs that interface over the web using GraphQL; how to deploy and manage complex cloud based applications over multiple services; how to reason about complex mathematical models and finite state automata; how to implement more scalable design practices should the need to increase service capacity arise, or more accurately how complex such tasks are; and how (and how not) to build design languages and response web applications.