MovieSpot website screenshot

MovieSpot

MovieSpot is an entertainment web application that showcases the most popular movies and TV series. It includes a login/signup form where users need to provide credentials to authenicate themselves. Once they have been authenticated they can browse the various movies and TV series. If any movies or TV series spark their interest they can bookmark them for future reference.

Built With

  • React
  • TypeScript
  • Next.js
  • TailwindCSS
  • Prisma
  • GraphQL
  • Cypress
  • Jest Testing Library

What I Learned

Deployment

I had issues dealing with different environments when the app went in production. In development, I was using a development environment variable as a base URL for my API calls. When the app was in production and made API calls it was using the development environment variable, which would result in the API call failing. To resolve this, I just determined whether or not the app was running in production or development and set a variable to it and the API calls would use this variable as the base to the api call.

I also ran into issues during the static generation of my pages because in the _app page I was making an API call to an endpoint to determine whether or not the user had a valid session. During static generation the server is not up yet so you can't make API calls during this time. To workaround this, I used a state variable to track whether the component was mounted or not. This just bypassed the static generation constraints, which might not be the best approach.

Type Safety

To bridge the gap between the backend and the frontend I used codegen to generate types for my GraphQL queries and mutations. The only thing that I didn't like about it was that I had to manually run codegen after I made a changes to the API. I also used TypeScript throughout the project and even made some hooks with TypeScript. For Example, this useSearch hook takes in an array of objects and returns a new array of objects that match the filter string based on a property of the object. In this case, the objects are movies and I return a new array of movies based on the searchValue. With generics I can ensure that whenever I use the hook the filterBy key has to be one of the properties of the objects in the array.

Password Management

For my authentication, I decided to use Bcrypt and Iron-Session. The role of Bcrypt was to hash the passwords for the login and signup form. Once I verified that either they are a user or they have successfully signed up, I then create a session for the user using Iron-Session. This means that the user no longer has to sign in as long as their session is valid.

Protected Routes

There are some routes in that app that should only be seen by users. For example the protected routes are [/movies, /tv-series, /bookmarked]. In order to protect these routes, I check the session when the user visits one of these pages and if there is no session they get redirected to the login page. I am checking the session client side, which means there is a little flash of content that is shown to unaunthenticated users.

;