Setting up a server with Node.js, Express, MongoDB, etc. 😼
Tags: tutorial, node, heroku, mongodb
Published: 2022-07-26 12:01:39

![a cute kitteh](http://placekitten.com/200/300)
## Intro  
These are the notes I took as I learned how to set up a server and API on my computer with Node.js, Express, MongoDB, and other dependencies.  
This is the order I like to set things up every time I start a new project. Depending on what I'm making I don't install some dependencies shown here or I'll install others.  

I took these notes while watching **[Mayanwolfe's](https://www.twitch.tv/mayanwolfe "Mayanwolfe's channel")** twitch streams and making my projects so a special _thanks_ and _shoutout_ to her.

---

>"We don't get got, we go get!" -#100Devs war cry

I got got many times while learning how to set up my servers and APIs. I'm hoping that with these notes I won't get got again and I prevent someone else from getting got too.

---

You'll need to have Node.js installed and accounts in MongoDB and Heroku, plus the Heroku CLI downloaded.

The main parts of your setup will be:
1. initialize npm and install dependencies
2. require what you need and listen
3. set up your .env and .gitignore files
4. declare your MongoDB variables
5. connect to MongoDB
6. set up your middleware
7. create your public and views folders and relevant files
8. set up your GET (and POST, PUT, DELETE)
9. push your server to Heroku 
10. bask in the glory of having built your own server

Let's go!

---

### Initialize npm and Install Dependencies  

Create your project folder and your server.js file inside that folder. I use the bash terminal in VSCode and the mkdir and touch commands.  
In the terminal, initialize npm:
```
npm init -y
```
The -y flag makes it so that you don't have to press enter a bunch of times.  
Next, install the dependencies that you'll use in your projects. Lately, I tend to use express, dotenv, cors if I'm setting up a local API, MongoDB, ejs sometimes, and nodemon.  

In the terminal again, write
```
npm i express dotenv cors mongodb ejs
```

The i stands for install, you can install your dependencies one by one (writing npm i each time), or all at once as above.
**Nodemon is different.** For nodemon, write
```
npm i nodemon --save-dev
```
as it's a tool to be used only while developing. You can go to your package.json file to check that everything is installed correctly.
While there, go to "scripts" and after "start": ... add 
```
"start": "node server.js",
"dev": "nodemon server.js"
```
don't forget the comma.
Now in the terminal you can write
```
npm run dev
```
and have the server restart on its own any time you make changes and save.  

### Require and Listen  

Just downloading isn't enough. You need to require the dependencies to be able to use them.

Back in your server.js file, write
```
const express = require('express')
const app = express()
const cors = require('cors')
const MongoClient = require('mongodb').MongoClient
require('dotenv').config()
const PORT = 8000
```  

app.listen() goes at the very end of your code, but you can set it up now to test that your server is working. In your server.js write
```
app.listen(PORT, () => {
  console.log(`Go catch the server at PORT ${PORT}`)
})
```
Save your code. Open your browser and write localhost:8000, or whatever number you put in your PORT variable, in the URL bar. Your console.log message should appear in your terminal, and since your server is not set up to respond with anything you'll see 
>Cannot GET /

in your browser, which is totally fine right now.  


### Set up your .env and .gitignore files  

If you were running nodemon, click in your terminal and hit Ctrl + C to get your repl back and be able to type again.  
 
Before pushing your project up to github you should create a .gitignore file so that your gigantic list of node_modules won't be pushed as well. .env is for sensitive information, like your mongodb password so that needs to go in your .gitignore file too. 
In your terminal write 
```
touch .gitignore .env
```

Open .gitignore and write
```
node_modules
.env
```

Save, then delete your PORT variable from server.js and write PORT = 8000 in your .env file (don't write const or let). 

Go back to your app.listen in server.js and change it to 
```
app.listen(process.env.PORT || PORT, () => {
  console.log(`Go catch the server at PORT ${process.env.PORT || PORT}`);
})
``` 
Save all your files.

Now you're ready to create a repository and start pushing.  

In your terminal write
```
git init
```
and then 
```
git add .
```
then go to your GitHub and create a new repository. On the set up page, copy the section from git commit .... to git push and paste that into your terminal, hitting enter until done.  

### Declare your MongoDB variables  

Assuming you're connecting to a MongoDB database for your project, in your server.js, between your requires and app.listen, write
```
let db,
  dbConnectionString = process.env.DB_STRING,
  dbName = '',
  collection
```
process.env.DB_STRING means that server.js is getting DB_STRING from your .env file.  
Go to your MongoDB Database Deployments page, click Connect, then click Connect your application. Copy the connection string then go to your .env file and write 
```
DB_STRING = 
```
pasting the connection string in the DB_STRING variable. The string will have \<password> in it. Replace that bit, including the <>, with your password. 
 
If you ***forgot your password*** or need to ***change*** it because you messed up the steps with git, .gitignore and .env files, exposing your password on GitHub, ~~like I did several times~~, click on MongoDB's Database Access under Security on the left and click Edit. Make sure you scroll down and hit Update User after changing your password. It takes a minute to deploy.

dbName is your database's name. Get it at MongoDB's Database Deployments page and click Browse Collections. There's a list of your databases on the left side. Write the name of the database you want to access in the dbName variable as a string.
Add, commit, and push to git.

### Connect to MongoDB

Back in server.js, write
```
MongoClient.connect(dbConnectionString)
  .then(client => {
    console.log(`Connected to the ${dbName} database`)
    db = client.db(dbName)
    collection = db.collection('')
})
```
under your MongoDB variables. In MongoDB, click on your database name to see the collections in it. Write the collection's name in between the single quotes in db.collection.
Save everything then write npm run dev or npm start in the terminal to start your server and see if you connected. Your console will log your messages.
Keep adding, committing, and pushing to git.

### Set up your Middleware  

After your MongoClient.connect, set up your middleware.
```
app.set('view engine', 'ejs')
app.use(express.static('public'))
app.use(express.urlencoded({extended: true}))
app.use(express.json())
app.use(cors())
```
Now your code knows to render ejs, access public files, handle urls, and parse api data.
Git add, commit, push.    

### Create your public and views folders and files  

In your terminal write 
```
mkdir public views
```
In your public folder make a js file and a css file, in your views folder make an index.ejs file. A quick way to do it using the terminal is writing 
```
touch public/main.js public/style.css views/index.ejs
```
in it. Fill in your content and remember to link css and js files in your ejs file, but you don't need to include public/ before the file names.

### Set up your GET  
You can set up a simple get to check that everything is working correctly.
Back in server.js after the middleware, write
```
app.get('/', (req, res) => {
  res.render('index.ejs')
})
```
Save your code, run your server and refresh your browser to check that your ejs file is rendering.
You can also put your collection into an array and render it in a console.log to check what's coming back from your database, but be careful with this if you have a lot of data. Refresh your browser to see the results.
```
app.get('/', (req, res) => {
  collection.find().toArray()
  .then (results => {
    res.render('index.ejs')
    console.log(results)
  })
})
```

Now you can either finish out your CRUD methods or  

### Push your server to Heroku  

~~Heroku needs to be able to access your DB_STRING. but it uses git commands so you need to delete .env from the .gitignore file when you push to Heroku.~~
~~Do **one last** save, add ., commit and push to GitHub, then delete .env from .gitignore.~~ Go to server.js and in the terminal write
```
heroku login
```
It'll open a window in your browser to login then you can close it when you're done. Back in the terminal, if you want Heroku to create a name for you, write
```
heroku create
```
If you have a name in mind write it after create but before hitting enter.  
Next, in the terminal, write
```
echo "web: node server.js" > Procfile
```
which will create a Procfile folder.  
 
Now ~~do a regular git add . and git commit -m'comment' but when pushing,~~ write
```
git push heroku main
```  

It's deployed! Now go to your dashboard in Heroku, click on your project's name, go to settings, click on Reveal Config Vars, write your db string variable name in the 'key' box and the string in the value box, and click Add. This will make it so Heroku can access your DB_STRING to connect to MongoDB. ~~Make sure you write .env again in .gitignore now, don't leave it for later. Whenever you push to git write .env, to push to Heroku delete .env.~~
Another problem I faced at this step was Heroku not being able to access my database unless I whitelisted all IP addresses at MongoDB. I think this is ok for my small projects but I'm looking for a solution to use when I start making bigger projects.  

Next, I want to review my CRUD methods and other tools like Mongoose.