If you don't know what Spinlist is, check out my introductory post.
In my introductory post, I talked about how I am building Spinlist in public and that I will be sharing the technical details of how I am building it. In this post, I'll be going over the tech stack I'm using to build Spinlist and the database schema I'm using to model the data.
Tech Stack
-
NextJS / Vercel
-
Supabase
-
Vercel
-
Spotify API
-
MusicBrainz API
-
NextJS / Vercel: I'm using NextJS because as mentioned in my introductory post, it is framework I've been meaning to learn. Apart from being something I've been meaning to get familiar with, it actually does provide some useful features for this project. Particularly, server-side rendering. SSR should come in handy for SEO purposes, particularly on the album pages. A long-term goal would be to get the SEO good enough so that if the user searches something like "Noah Kahan The Great Divide", the album page for it would come up in the search results. Since Vercel is the company behind NextJS I'm just defaulting to using them for hosting since they make it extremely easy to get up and running quickly.
-
Supabase: I'm going with Supabase for database hosting since they provide a managed postgres db that I can quickly get up and running with. Their documentation is also fantastic. Apart from just database hosting, they also provide an API for user authentication. Since it's all well integrated, I'll be using Supabase for user auth and as my database.
-
Spotify API: I'm going with Spotify API as my search service. They provide a search endpoint that I can use to pull in results when a user conducts a search on Spinlist. They also provide various endpoints to get metadata on artists and albums.
-
MusicBrainz API: MusicBrainz provides some metadata that Spotify lacks, particularly around album "grouping". MusicBrainz provides a nice interface where all versions of an album are grouped under a single entity. This is extremely helpful to prevent fragmenting of the reviews, i.e preventing the situation where UserA leaves a rating on the original album, and UserB leaves a review on the release version. We want to ensure that both reviews contribute to the same album, otherwise are data becomes fragmented.
Database Schema
Here is the database schema I'm using for Spinlist.

It's a pretty straightforward schema. I think the most interesting part is the "release_groups" and the "mappings" tables. I debated keeping just the "albums" table and not having the "release_groups" table, but I think it is important to have the concept of a release group to prevent fragmentation of reviews.
The "mappings" table is just a simple join table that allows me to link albums in my database to their corresponding entities in Spotify and MusicBrainz. This way, when a user searches for an album, I can pull in data from both Spotify and MusicBrainz and link it to the same album in my database.
As you can see, there's also the "favorites" table which I'll get into in a different post. For now, I'll stick to this schema for the MVP. I may end up adding more tables or fields as I go along, but this is a good starting point.
Update (2026-04-30)
I updated the schema to add a "join" table between artists and a release group. This was necessary because a single album can have multiple artists. With the schema I had above, only a single artist could be linked a release group. The updated schema now supports a many-to-many relationship between artists and release groups.
New schema:
