Side Project #2 - Oyego
Tags: nextjs, graphql, react, spotify
Published: 2021-08-01 02:18:02

---
title: Side Project #2 - Oyego
published: true
description: Oyego - The social app for music lovers (POC)
tags: nextjs, graphql, react, spotify
cover_image: https://i.gyazo.com/67b72513948cdd03a2ab094f03b93619.png
---

### Introduction

I really enjoy watching movies and then rating them using an app called [Letterboxd](https://letterboxd.com/). I then thought, "Well wouldn't it be cool if we could rate music as well?" And that's how Oyego was born - it's basically Letterboxd, but for music!

You can check out Oyego [here on Heroku](https://oyego.herokuapp.com/)

- Please note that you will be unable to log in if I have not personally reached out to you. This is because the application uses Spotify's API, and the app is currently in Development Mode, so we are limited to a max of 25 users that I have to add in manually. 😟

If you would like to check out the demo video/source code, you can do so [here on Github](https://github.com/jwaang/oyego).

If you've watched the demo video, you're probably wondering if it was a good idea to list ALL of the most recent reviews on the home page, why the search page only returns only 10 results, or maybe something else. All of this was intentional, and I made these decisions to limit the scope of my project. This project was meant to be a proof of concept, so I didn't want to bombard myself with a huge list of features to add because I have more side projects that I want to work on. Who knows, maybe I'll pick this up another time to turn this into a more thought-out application with all the bells and whistles. 🤷‍♂️

### Tech Stack

This project was my first time using NextJS, and I have to say that I like this framework a lot. There were many cool out-of-the-box features that I could use, like next/auth, next/img, next/router, and more, that helped me with my project. I also wanted to learn more about server-side rendering and see how it differed from client-side rendering.
I also used GraphQL and Apollo Client/Server (also first time) to learn more about back-end design and programming and explore other backend technologies.

### My Development Process

The first step to any project is to design and plan everything out. But before doing so, I first had to explore Spotify's API because I wasn't sure if I could use it to search for items in their database (hint: you can 🥳). Once I had confirmed that this was possible, I then began creating mock-up designs. I started with Figma and drafted how I wanted my user interface to look. You can view a screenshot of my design below. Please note that I am not a Figma master; my thoughts are (literally) all over the place.

![Figma](https://i.gyazo.com/a319e44ef8c90da25dbebff2e5d7311e.png)

Once I had the user interface created and the workflow detailed, I could begin planning what queries or mutations I needed to create. I was aware that there could be an endless amount of features to add in, so I decided to limit my list of features and focus only on the key components. Here's the list of features that I came up with:

- Spotify authentication for login page
- Fetch all reviews in the database for the home page
- Fetch specific reviews in the database for the user profile page
- Search Spotify's database for albums (yes, only albums) for the search page
- Create reviews
- Update/Delete reviews, only if you're the user who created the review
- Style and animate everything, so it looks litty

Once I had everything planned out, I began developing. I created a NextJS project and learned about next-auth providers, making it extremely simple to set up a Spotify login. Once I setup authentication, I began setting up my first Spotify search query on GraphQL. Setting up the types and resolvers was straightforward, but I did come across my first issue. To hit a Spotify endpoint, you have to pass in an access token that can be used once the user is properly authenticated with Spotify. I know that this was possible with the context argument, but I couldn't figure out how to communicate between the client and server even after spending two days on the issue. As a result, I decided to pass in the access token as a parameter for the query itself, which isn't ideal 😢. After that, everything was smooth sailing from there (sort of)! I continued to work on my queries and mutations and would work on the front-end piece concurrently to make sure everything was connected and working properly. There was a time where I did spend an hour trying to figure out why my query wasn't working until I realized I was missing a curly brace in my gql statement... But besides that, I also learned about updating the cache in Apollo which I thought was very useful and important.

Once I felt like the backend was complete, I could begin working on styling everything. I first added in the background waves I had created in Figma. It wasn't easy to get everything the way I wanted it to, but I eventually figured it out after many hours 😩. After that, I just started styling the hell out of EVERYTHING - the buttons, the cards (using the glassmorphism effect), the pages, the navbar, etc. I usually use prebuilt UI components, but I wanted to challenge myself and see if I could design something, and I gotta say I'm pretty proud of myself. I usually copy and paste flexbox code and hope that it works, but I actually sat down and decided to dive deeply into flexbox. During this time, I also cleaned up the code base and fixed some small bugs floating around. AND last but not least, I thought I needed animations on this application because everyone loves animations 😩🔥. I had heard about Framer Motion a couple of weeks prior and decided to give it a try. All the sick-ass animations you see on the application were 100% accomplished with Framer Motion, and I'm super happy with how it turned out. It was effortless to set up and learn, and I feel like I just scratched the surface with what I know. I will definitely be using this again!

The last issue that I faced was with next/img. What's really cool about next/img is that it optimizes the image on the server by lazy loading it in the application for faster load times. One caveat (or maybe not, idk) is that you have to configure the hostname of the image url before doing so. So if your hostname is static, then it's all good! But if it's dynamic, well... In my application, every time a users creates a review, it would save the url of the user's profile picture in the database. Spotify, unfortunately, uses a dynamic hostname to host the user's profile picture - meaning that the url was constantly changing. As a result, I had to remove the user's profile pics on their review cards.

Once I felt confident in my application, I could then deploy it to Heroku! This part honestly sucked because I spent a long time trying to figure out why my callback url wasn't working in production even though it was working in my local. In production, after the user pressed Sign In, it would set the redirect url to the localhost url INSTEAD of the redirect url provided in the Spotify developer portal, causing a callback error 🤬. In the end, I realized that it was because my NEXTAUTH_URL was not defined and so NextJS was defaulting to the localhost url.

### Potential Add Ons

As mentioned earlier in the introduction, this application is still missing a ton of features. Here are some more features that can be added to this project:

- Follow feature that allows users to follow others
- Like/Comment feature allowing users to interact with other reviews
- Instead of displaying everyone's most recent reviews, we display reviews only from the user's following list
- Pagination or dynamic scrolling for home page and search
- Allow users to review songs, not just albums
- A section to display the most popular music/reviews/users
- Form Validation
- Mobile responsiveness
- ...and more!

### Conclusion

I had a great time building this project and got the chance to learn a lot more about NextJS and GraphQL. I did face a ton of challenging obstacles along the way, but I found that to be extremely rewarding in the end. :)