A fully functional movie finder written in React with a Node JS Express backend connecting to MongoDB
Note: Application is hosted on heroku, please give the application a few extra seconds to spin up from non-activity mode.
- Email: [email protected]
- Password: Password1!
View Raidenn Site : https://raidennapp.herokuapp.com/
View Figma Design : https://www.figma.com/file/rIZCKESgMboi0SjV4Jq9BG/Raidenn2?type=design&node-id=36%3A505&t=BZtUIsY37LYOPal2-1
- Search for the latest and upcoming movies
- Save movies to your watchlist
- Get a link directly to the service where you can watch the movie
- Leave a comment on your thoughts on the movie with a rating
- View the movies you put on your previously watched and want to watch list.
Raidenn is a portfolio project which was built to further improve the author's skills. This project can be thought of as a guide to a developer interested in building a React site built around redux that makes use of MondoDB as their cloud database solution. This project also implements a good standard practice for web security, JWT. Raidenn also makes use of a free database api service known as MovieDB in order to get the movies shown in the project. This project can be broken up into two parts which consist of the main packages used:
-
Backend
-
Frontend
If you are interested in getting started on your own personal project structured like this one I would recommend the Youtube channel Traversy Media, he has a 5 part series on the MERN Stack which was used as guidance on this project. Also below I have done a breakdown of explaining the project journey from backend to frontend.
- Github Account
- MongoDB Account
- NodeJS
- VSCode Editor (Recommended)
Setting up MongoDb Account has a few extra steps and I recommend watching this time tagged Youtube video from Traversy Media to get correctly setup. A reminder to also create your own .env file in your project in order to connect to mongoDB. Below is an example of the .env file structure needed for this project :
Once setup with all the necessary accounts, now we can clone the repository.
How to Clone a Github Repo
Once cloned you will need to run npm install
command in your terminal in both the root project folder and the frontend folder as there are two seperate node modules on this project.
Finally, your last step is to run npm run dev
from the root of the project. This will run both the backend api service as well as the frontend at the same time. Enjoy :)
This marks the end of the first version of the project, I am doing this as I would love to make improvements in the future for a v2 which would be a much better user experience and as well up the quality of the site in my opinion. Below are a little of a few additional ideas/features I am planning to integrate into Raidenn v2 sometime in the future:
- A section to get recommended movies to the user based on their genre preferences.
- Allow the user to update movies genre preferences.
- Share a movie link to a friend.
- Restrictions to only allow a user to have 1 comment per movie.
- Smoother animations when navigating through pages.
- Smoother load of Images on the site.
Lets first cover the backend and then explain how that connects with the frontend of the project as well as the MovieDB database api service. For the backend everything has been implemented with NodeJs and Express, with the file structure been created for MondoDB in mind. We will use the Watchlist as an example to get an understanding of the flow, as all other concepts follow a fairly similiar direction.
Watchlist consists of the 3 files all in specific folders. These files are watchlistModel
found in models folder, watchlistController
found in controllers folder and watchlistRoutes
found in routes folder.
-
watchlistModel
- The purpose of this file is define a set schema for a watchlist instance. Below you can see a schema is created from the mongoose(Related to MongoDB) library. Each new variable type must contain a
type
and is recommended to have arequired
in order to manage validation later on when adding a new watchlist instance.
- The purpose of this file is define a set schema for a watchlist instance. Below you can see a schema is created from the mongoose(Related to MongoDB) library. Each new variable type must contain a
-
watchlistController
- This controller file holds the functionality we want the
watchlistModel
to be able to. It holds the general CRUD functions for the watchlist instance.
- This controller file holds the functionality we want the
-
watchlistRoutes
- The routes is the final piece that binds each CRUD function to a specific route. As below you can see getWatched function which is imported from the controllers file is being binded with the route
/watched
. Additionally you can see that same line containts aprotect
function, which is imported from an addidional folder called middleware. This protect function contains the logic to only allow an authorized user to hit our api endpoint, which is done with a JWT token. Later in this breakdown we will review the middleware folder to show how it authorizes and validates requests.
Now for the Frontend side of the project with the example still being the watchlist.
The important files will be located in the src folder. Every Schema from the backend will be referenced in a frontend folder called
features
. In features there is awatchlists
folder containing two files,watchlistService
(Makes use of Axios) andwatchlistSlice
(Makes use of Redux Toolkit).
- The routes is the final piece that binds each CRUD function to a specific route. As below you can see getWatched function which is imported from the controllers file is being binded with the route
1.watchlistService
- This service bridges the gap between the backend and frontend. This file contains all API calls that can be made for the watchlist schema. Axios was used in making the api requests and attached to each request is the user's Bearer Token. Below is an example of the structure of
getWatched
api call:
2.watchlistSlice
- This file hands the redux side of the project. Here an exported function is created for each imported api call from the watchlistService. If an api call is fulfilled the response is then saved to a Redux state variable. This will allow the project to access these variables from any frontend file for display purposes. Below is an example of a that function mentioned:
Finally in the Watchlist.js file under the pages folder we make a reference call to that redux variable in order to get the data it is holding. Below you can see an example of how that reference is done. useSelector
is a function from the react-redux package.
This folder contains the logic that handles every api request that hits the backend api. This is a good practise to ensure that the user hitting the api endpoint is authorized to do so as an example. In this folder we have 3 files which we will breakdown: authMiddleware
, validateMiddleware
and errorMiddleware
.
1.authMiddleware
- This file contains the logic to handle api endpoints we want to be protected, only allowing an authorized user to hit the protected endpoint. This file firstly checks to see if the request sent has a Bearer Token, if it does not, it rejects the request and sends a
Not authorized, no token
response. If a token is attached in the request header then a check is done to validate if its a valid token with theJWT_SECRET
.
- If it passes these checks then it hits the
next()
command which tells the program to hit the next command in the the chain. In the below Image it shows it will go from the protect function that we just reviewed in theauthMiddleware
to thegetWatched
function which is the actual api function the user requested.
2.validateMiddleware
-
This file was created with the purpose of handling input validations a user makes on the site, fields such as passwords, email, username. This validation ensures the user has entered in a valid input, meeting the requirements. For example making sure the user's new password has 1 Uppercase and symbol included. We don't just want input validation to be done on the frontend as this can be avoided by a user if they choose to directly hit the API request themselves outside of the site environment. Do server side validation ensures the correct inputs are being accepted in the database. Below we can see we have our
validate
function. It holds 2 regex lines that define the validation which has to be met, one for a secure password and the other for a valid email. -
A check is then done to see if the input type say for example
password
matches its regex pattern. If it fails it will throw an error message back to the user on the frontend. If it passes, then it will hit thenext()
command and then continue to the actual api function in order to update the password or register a new user.