January 2024 - Present

Unfortunately, Melody is only available to be run locally (for now) due to Spotify API restrictions.
Melody was an app idea that was inspired by the popular food rating app Beli. Unlike traditional rating apps of any kind, Beli does not let you explicitly set the number you want to rate a track. Instead, it gamifies the process by making you pick your favorite songs against each other. I decided this could be a great concept to port over to music, so I did! I learned alot of things along the way.

The first large challenge was managing user sessions and authentication. I used Auth.js (previously NextAuth.js) to create and encrypt sessions. However, utilizing these sessions in a secure way and fetching data with them was a design problem that took some extra research! In the photo above, user sessions were utilized to fetch the users songs. To do this securely, the session data is only accessed in the server, which means we have to set up API routes where requests are handled on the server. I utilized Next.js route handlers to build GET and POST routes in my project which acted as a proxy between the frontend and my actual Flask backend. I did this so that data could securely be fetched by Next.js on the server, and then Next.js send the request with the session information to the backend. This keeps session data like the JWT from being accessed by the client.


This screen pops up when you decide to rate a song. Here I am rating Little Alient Spaceman by Dayglow. Initially, you choose your general opinion about the song. This prompts the app to fetch a song to rate against it (which you previously rated). Choose wisely!
One of the biggest features that required research was the global audio player, which is shown at the bottom of this screenshot. This clientside feature had to be working regardless of what was happening in the app in order to be truly global, like on SoundCloud. This was a great opportunity for me to learn React context, which enabled me to pass data to any child component. I learned a great deal about when React decides to re-render components, and had to keep this in mind for efficiency.

When a song is rated, Melody gives it a ranking and shows the user.
Under the hood, something important to me was making sure that the process of rating was seamless, including client-server syncing happening without any hiccups. The screen shown above serves two purposes, (1) it shows the user the score and (2) it allows the client to finalize the new rankings and send it to the server to sync. To minimize the number of requests, syncing is only done after a user has chosen through enough songs to get a final ranking.
Designing the database to keep track of all the rankings required some deliberation. I decided to simply store the song identifier along with the index of that song in a greater ranking "array". I had previous ideas of using some PostgreSQL arrays or other more complicated data types, but decided to store the index for simplicity and do upsert functions to sync data sent from the client.
The algorithm to score songs is simply a binary insertion sort. Since the database stores indexes, the existing list is always "sorted" by ranking. However, the ranking numbers themselves are derived client-side from the ordering returned by the server. This is where the three initial ranking categories come into play. Songs that are initially ranked with a thumbs down are scored between 0 and 3.5, with thumbs up songs being rated between 7.5 and 10 (medium rankings are in the middle range). Each songs index is calculated against the number of songs rated and then linearly transformed into the new range corresponding to which array they are in (good, ok, or bad songs). In the screenshot above, Little Alien Spaceman was ranked in the good category, which makes the floor of the ranking 7.5 and the ceiling 10. The nuances of where in that range it falls is done by comparing it against other songs in that category which are chosen via the step by step process of binary insertion sort. Based on the nature of the sorting algorithm, as the user grows their database of songs rated the amount of songs they must rate against for any given category will be about log(n) where n is the number of songs in the category.

Melody gives Little Alien Spaceman an 8.2 - it's a pretty good song!