Guitargeki - Competitive Guitar Battles

Guitargekis are competitive events where guitarists submit audio/video performances of a pre-chosen theme/song. At the end of each match or event, a panel of judges vote for their favourite submission or rate each submission. The winner is the submission with the highest number of votes or rating.
Guitargeki currently consists of an API and a basic website to view data.
The API uses the following tech:
- Docker
- PostgreSQL
- Node.js (hapi framework)
- nginx (as a reverse proxy)
- Auth0
- GitLab CI/CD
The website uses the following tech:
- React
- styled-components/styled-system
Additional links:
History
In late 2018, I joined a Discord community comprising of guitarists with a focus on anime and video game music. The server hosted events called Guitargekis. These were battles where two or more participants would create covers of a chosen theme/song.
After a few months, one of the members decided to create a basic Elo leaderboard in C++ to rank the participants. While this was a good start, all the data was stored on his machine so we would have to ask him if we wanted to view the rankings. Furthermore, we didn't have an easy way to view past submissions. This motivated me to create the first iteration of the Guitargeki database.
First iteration
The first iteration of the database was created in Google Sheets. Here are a few things that helped me choose Google Sheets:
- Easy to get started if you have previous Excel experience (or even if you don't!)
- Google Sheets API which meant a front end could easily query the data
- Google Apps Scripts enabled me to write custom code to calculate the Elo rankings
- Google Forms allowed me to create custom forms so that participants could enter their submissions
While these features seem great at first, I found that the API and SDKs were hard to use and the documentation was also confusing. Because of this, I decided to build something more robust.
Second iteration
The second iteration used Node.js for the back end and PostgreSQL to store data. My frameework of choice for creating the API was Express.
One of the things I liked about Express was that it wasn't too opinionated. You could architect your API however you wanted so it gave you a lot of freedom. Unfortunately, this freedom ultimately made me move to another framework.
One thing I knew I wanted from the API was an auto-generated Swagger/OpenAPI file and docs page. Another thing I wanted was robust error handling and validation. As I built these things, I realized that I was basically building my own framework. At this point, I decided to switch to a framework that supported all of these.
Third iteration (current)
After some research, I landed on hapi. Here are a few reasons I enjoyed using hapi:
- Writing routes - Routes are very easy to write as they are basically one big object. This object contains properties such as the route's HTTP method, path, response code, validation options etc.
- Error handling - hapi handles a lot of errors for you automatically (such as validation and auth errors) and sends back the appropriate status code.
- Plugins - There were quite a few plugins I found to be quite useful. Some plugins I used were for working with JWTs, rate limiting and auto-generating a Swagger spec and docs page.
- Validation - hapi has built-in support for validation using the joi library which features a very succint, easy to use and extensible API.
Future plans
- Generalize the platform to support multiple communities. Each community would have their own leaderboards, submissions, rules etc.
- Move over to a serverless architecture for scalability and less DevOps. The plan is to move the data over to FaunaDB and move logic over to serverless functions on a platform such as Google Cloud Platform or Netlify.
- Proper front end so people can create their own communities and enter their own submissions.