MERN Full-Stack Tutorial 2020 — Part 1 (backend/server-side)

This tutorial is another resource for people to use when learning how to build a full-stack MERN application…except mine will include saving to local storage and using Redux for state management…

Demo

We’ll be building a weather web app called Weathering With You.

Screenshot of Weathering With You — MERN web app

This app will be able to let you, the user, enter a zip code, choose Celsius or Fahrenheit, and then get the current weather data at that time when you click Save.

This app uses a free weather API that we will utilize and store that data in local storage/mongo, per your choosing, and use Redux as a state manager so everything updates super quickly when interacting w/ the UI.

The left-hand panel will be the current zip code’s weather information and the right-hand panel will be a list of 10 most recent queries.
Also, if you queried 1 zip code and refresh the page, it will update the left-hand panel to the current weather information for the most recent zip code you have queried.

Demo: https://mernweatherapp.herokuapp.com/
**disabled mongo connection in this app — but this tutorial can show you how to connect and use

“Weathering With You” Demo

What can it do? What will I learn from the entire project? What technologies will I use?

  • Learn to use a free API, openweathermap’s weather API, to dynamically get weather data based on zip code (USA only)
  • Aside from MERN (Mongo Express React Node), we’ll be including Redux as our state manager
  • Ability to save data into LocalStorage so that data is stored locally and don’t need to rely on Mongo (depends on use case)
  • React Bootstrap as our frontend component library

Getting started

Install Node (at the time of this writing, current stable version of this tutorial is v12.18.3) by going to the website and clicking Download

Download buttons for Node version 12.18.3 for the Stable version (at this time)

To verify if it has downloaded correctly — go to your terminal and check which version of Node you download by typing this in command line:

node -v
Example of checking Node version

Once Node version is confirmed, create a new directory called
mern-weather-app and then go into that folder.

These are the commands to create a new directory and change directories within command line:

mkdir mern-weather-app
cd mern-weather-app

We can now initialize our project using npm within the root folder of our mern-weather-app by using this command:

npm init -y

Now, we can install all the dependencies that we need:

npm i axios body-parser cors dotenv express mongoose

Here is the list of all the dependencies we just installed:

*I included the links to all the dependencies home page, so feel free to check out more info about them.

Now let’s install our dev-dependencies, which are packages that’ll help us be more efficient during our development process, but won’t be included in our Production build:

npm i -D nodemon concurrently
  • nodemon: automatically restarts node app when file changes are detected
  • concurrently: runs multiple commands concurrently
What your current package.json should look like
Example of setting up package.json with dependencies

Add .gitignore

Add a .gitignore file to your root directory so that when you push your project to github, we do not push any sensitive data or unnecessary files.

root/.gitignore

Download Git

Download Git for your specific operating system and run it.

Once downloaded, in your terminal/command line, check to see if it’s working by checking the git version that you have

git --version

We need git to connect to github and make commands to utilize version control.

Connect to Github

  1. Go to https://github.com/new to create a new repo or click on any action button in github to create a new repo(make an github account if you don’t have one already)
  2. Create a repo name for what you want to call this project, choose either public/private, I’d suggest Private in case you push anything sensitive (like api key or mongo connection credentials) by accident to your repo
Creating a new repo screen

3. After you created a repo, you should see this screen:

Instructions on how to connect your project to github

4. We’re going to follow the …or create a new repository on the command line instructions, but not all of it line-by-line.

5. Go back to your project’s terminal and make sure you’re in the root directory. These are the commands that we’ll use to connect to our newly created repo.

git init
git add .
git commit -m "first commit"
git remote add origin https://github.com/[username]/[app name].git
git push -u origin master
Show terminal commands to upload project to github

6. You should now see your project when reloading your project page on github

Checkpoint #1 https://github.com/JinKim7/mern-weather-app/tree/1.setup-packagejson%26gitignore
File Changeshttps://github.com/JinKim7/mern-weather-app/pull/1/files

Your working project directories should look similar to the checkpoint above. These checkpoints will lead you to branches that are code complete with everything we have done thus far.

So, you can refer to them if you need guidance on where some of the code should be placed and whatnot.

Create Backend Server

Make a new directory called server within the root directory and then create a server.js file to be like this.

server/server.js
  • require("./api") in line 14 — This means that we’re going to use an entire directory to organize all our API endpoints instead of putting all the API endpoints in server.js

Now, create a new directory called api in the /server directory and create two files, index.js and weather.js

server/api/weather.js
server/api/index.js
  • There are comments within each file to briefly explain what most of the lines of code does, but here’s a brief explanation…
  • weather.js — we’re creating a weather class to be able to connect to the weather api and be able to get weather data to send back to our frontend later on in this tutorial.
  • index.js — depending on which type of endpoint we call, this will be where our router lives to help direct which type of traffic goes where. i.e, if we have a GET /weather endpoint call, our router is able to dictate what kind of operations need to take place to satisfy the call as expected. Same goes for the POST request.

Checkpoint #2 https://github.com/JinKim7/mern-weather-app/tree/2.setup-server-and-apis
File Changeshttps://github.com/JinKim7/mern-weather-app/pull/3/files

Create Environment Variable file | Use Weather API Key

One thing mentioned in the weather.js file that we have not done yet is creating a file for environment variables (more info on what env vars are here).

Before we create an .env file, let’s get our weather api key since we’ll be using it within this file.

Got to https://home.openweathermap.org/api_keys and create a profile (the direct link should already take you to the API keys page, if you’re already logged in).

Where you can find your API key.

Now, create an .env file within the root directory (mern-weather-app) and include this in that file:

WEATHER_KEY=[weather API key from home.openweathermap.org/api_keys]

or more of an obvious example: WEATHER_KEY=b8a1e654asdf654asdf654

Note: assuming b8a1e654asdf654asdf654 was my real API key (fyi, not my real API key for the 1337 h4x0rs).

All-in-all, it should look like this (also double-check the file/folder structure):

Example of what your project should look like at this point.

Checkpoint #3 https://github.com/JinKim7/mern-weather-app/tree/3.ENV-file
File Changeshttps://github.com/JinKim7/mern-weather-app/pull/4/files

❗️❗❗ Do not push your .env file to Github because if your repo is public, everyone can see your secret credentials❗️❗❗

  • I’m including an ENV file that’ll have comments within the file on how to make the .env file.

Test What We Have So Far

To test our weather API thus far, add this script to the package.json

"start": "node server/server.js"
Added “start” script to our package.json

Now, you can run the command, npm run start , within your terminal to test our static GET endpoint to the weather API to get the weather data for zip code 98052 within the US (United States) by going to the URL localhost:5000/api/weather

Connect to Mongo

Create a new account at mongodb.com and you will land on this page to Create a cluster

Choose the FREE tier when creating a cluster.

Choices when creating a cluster (for this tutorial, choose the free tier)

On the configuration page for creating your cluster, these are the options you will want to choose:

  • aws
  • Oregon (bc I live on the west coast, if you live in east coast, choose N.Virginia — if you live in the mid area…pick your poison)
  • M0 Sandbox
  • No Backup
  • Customize your cluster name if you want to…I’m not.
Creation Cluster Configuration Page

This should be the main page you end up on when your cluster has been created:

Correlate the numbers label in the picture to the list underneath
  1. Database Access — this will allow certain users, restricted permissions on what they can do once connected to the database.
    You will need to create a new user, so you can use this newly generated user’s credentials to connect to mongo from your app.

*fyi, only using this user/pass combo as temp credentials to show the example more clearly. It will already be deleted by the time this tutorial is published.

2. Network Access — this will give you access to connect to your mongo database based on which network is connecting to it. It could be your personal IP or anywhere from the world.

Whitelist IP Address within Network Access

*I chose Allow Access From Anywhere for the sake of this tutorial and only temp. You will be unsuccessful if you try to hack attack me.

3. Connect — will give you the connection string for us to use within our code to route and connect to mongodb.

  • Choose Connect your application to get our connection string
  • We can now see the connection string to copy/pasta within our code:
mongodb+srv://jin:<password>@cluster0.luzag.mongodb.net/<dbname>?retryWrites=true&w=majority

More obvious example:

mongodb+srv://jin:t4EoZWQdJiyOPsu9@cluster0.luzag.mongodb.net/Cluster0?retryWrites=true&w=majority
dbname is Cluster0, with the uppercase C

Add the mongo connection string to your .env file and have your key be DB for your connection string to follow suit.

Your .env should look like this now:

current .env example

To connect to mongo, we first need to add/update some files.

First, updating the server file. We are using the mongoose package to connect to mongo below…

server/server.js
  • using process.env.DB to get the DB key and mongoose to connect to the database

Run npm run start and you should see Mongo Connected... with your terminal.

MongoDB Connect…

If mongo does not connect, then…

  • double-check you have the right ip address whitelisted (possible your ISP changes your IP address after a few days making it dynamic, or using connect from anywhere option)
  • Your username/password match and the password actually created the user (if you used an easy password like password123 , it will not create it for you and have to use a diff password)
  • The dbname is the same casing as you see within the UI
  • the routing to the .env file is correct
  • many other possibilities why it’s going wrong 🙃

Update Files to Integrate Mongo

We are adding a database model for our weather data which is going to be used to template out the structure of what’s going to be saved within mongo.

Create a new folder and file called src/models/Weather.js below:

server/models/Weather.js
  • This model is based off the structure the weather api will give us here.

Update the server/api/weather.js file to take in weather data and save it into the mongo database; if a document already exists, then we want to replace it (upsert) based on the zip code as our unique identifier, if the document doesn’t exist, then add the weather data.

server/api/weather.js
  • const Weather— let’s us use the weather model that we just created
  • saveWeatherDataToMongo — execute mongo operations to save the weather data uniquely based on the zipcode filter (replace if a zipcode already exists in mongo, if not, create a new document and save).
    - This is the specific endpoint we’re using: https://openweathermap.org/current#zip
  • getWeatherDatafromMongo — tries to find a document w/ the same zipcode, if it cannot find one, then it will return null
  • findOneReplace — helper method to find and replace in mongo

Finally, add the post request in server/api/index.js so we can store weather data into mongodb.

server/api/index.js
  • the POST /weatherMongo will be used later on in the tutorial when connecting frontend to backed.
  • the GET /weatherMongo won’t be used in our tutorial, but it’s here for you to play around with it.

Checkpoint #4https://github.com/JinKim7/mern-weather-app/tree/4.mongo-integration
File Changeshttps://github.com/JinKim7/mern-weather-app/pull/5/files

Let’s test our Mongo integration!

  • run npm run start in the terminal of your root directory to start your backend server
  • Go to http://localhost:5000/api/weatherMongo?zipCode=98052 to test out your GET request to see if your endpoint is working and be able to get weather data.
    Surprise! You should see null on your screen
null response from GET request to mongo
  • We’re seeing null because our mongodb does not have the weather data information yet. Since we don’t have our frontend to make our POST calls to the backend, we’ll have to use our Console to make the POST call for us (or you can you Postman or any other REST api clients — you can find some good chrome extensions).
  • Copy/pasta this code snippet into your chrome console (right-click > inspect > Console tab)
fetch('http://localhost:5000/api/weatherMongo', {
method: 'POST',
body: JSON.stringify({
zipCode: 98052,
tempMetric: "imperial"
}),
headers: {
'Content-type': 'application/json; charset=UTF-8'
}
})
.then(res => res.json())
.then(console.log)
Screenshot after the POST call
  • Refresh the page and now it should populate the weather data from mongodb.
GET request to get weather data from mongodb
  • Now, to check the data saved in mongo, go to cloud.mongodb.com (it should redirect you to your dashboard if you’re already logged in, if not, log back in) and click on the Collections tab
Collections tab within Mongo
Testing mongo integration

Done!…for now…(you finished the longest section of this series).

In the next section, we’ll move onto frontend for this application!!!

Additional Resources

Here are links to further your knowledge on all the tech we used today.

Similar Tutorials

Here are other tutorials that also give similar teachings, but we all have our own unique ways of teaching and presenting data.

Hopefully, one of these, or mine, helps you to become successful in learning of what you came here for 😃

They’re all PHENOMENAL(!!!) tutorials and highly recommend them! My tutorial glosses over technology-specific details

c#/.net dev@day — js dev@night 🦄

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store