Build a REST API with Node, Express & MongoDB!

In this project we will be creating a way for people to subscribe, update, retrieve and delete data on Youtube accounts. We’ll do this by coding a REST API that lets users interact with our Youtube database by defining what info our database will accept and how it goes about manipulating that data depending on what a user would like to do.

A big shoutout to Web Dev Simplified for the knowledge he was able to pass along in helping me create this tutorial. If you’d prefer to see a video tutorial for this then I highly recommend checking out Web Dev Simplified’s tutorial here: https://youtu.be/fgTGADljAeg

My Github Repo

If you get stuck or think you did something wrong and can’t quite figure it out, refer to my Github Repo of the completed application here: https://github.com/Beznet/node-api

Project and Dependency Setup

Important Prerequisite : Make sure you already have MongoDB installed and setup on your machine before starting this tutorial. Here is a link to a guide that MongoDB provides on their website: https://docs.mongodb.com/manual/administration/install-community/

First, let’s open our terminal and create a new directory for this project. Now in our terminal type npm init to start and just leave all fields blank for the time being by pressing ENTER through each question. Next we want to install Express and Mongoose:

npm i express mongoose

Then once those two are finished being installed we need to also install dotenv and nodemon by entering:

npm i --save-dev dotenv nodemon

Note: --save-dev from above will save development-only dependencies without saving them to production

dotenv will allow us to pull in environment variables from a .env file and nodemon will update our local server each time we save

When we ran npm init earlier it created a package.json file. In this file under the scripts we want to replace that ‘test’ script with our own script that starts our server with nodemon:

  "scripts": {
    "devStart": "nodemon server.js"
  }

Setting Up Our Server

Ok now we get to create our first file called server.js . Once created, at the top of the file we want to include all of the dependencies that we will need for our project:

const express = require('express')
const app = express()
const mongoose = require('mongoose')

When we want to test and make sure our server is working, we will run this function to listen on port 3000 and log a string if its successful:

app.listen(3000, () => console.log('server started'))

At this point our server.js file should look like this:

const express = require('express')
const app = express()
const mongoose = require('mongoose')

app.listen(3000, () => console.log('server started'))

Connecting to Our Database

This next highlighted chunk of code is how we connect to the database. I’ll explain it line by line:

const express = require('express')
const app = express()
const mongoose = require('mongoose')

mongoose.connect(process.env.DATABASE_URL, { useNewUrlParser: true })
const db = mongoose.connection
db.on('error', (error) => console.error(error))
db.once('open', () => console.log('connected to database'))

app.listen(3000, () => console.log('server started'))

The first line allows us to connect to the database using Mongoose. You may be wondering what DATABASE_URL is, this is the location we want for our database which I have defined in our .env file. If you haven’t created a .env file, now would be a good time and then you can set the DATABASE_URL there:

// .env file

DATABASE_URL=mongodb://localhost/subscribers

After we have our DATABASE_URL defined in our .env lets hop back to our server.js file. Now to reference variables in our .env file we need to require the dotenv package at the top of our server.js file:

require('dotenv').config()

After we get that package required the line of…

 mongoose.connect(process.env.DATABASE_URL, { useNewUrlParser: true })

…will now function appropriately.

Moving on, we have set db to mongoose.connection as a syntactically easier way to reference our database. Next, we’ve defined what happens when the database encounters an error, which is to log the error itself. If there’s no error we want to log the string of connected to database to our terminal.

Ok! That’s a lot of stuff. So to sort of put everything together our server.js file should now look like this:

require('dotenv').config()

const express = require('express')
const app = express()
const mongoose = require('mongoose')

mongoose.connect(process.env.DATABASE_URL, { useNewUrlParser: true })
const db = mongoose.connection
db.on('error', (error) => console.error(error))
db.once('open', () => console.log('connected to database'))

app.listen(3000, () => console.log('server started'))

Let’s Test Our Database Connection!

At this point we can now test out our connection to the database to make sure everything is working smoothly. In our terminal, let’s go ahead and start our database by typing mongod and then in another terminal tab let’s start our server with npm run devStart . If all went well, we should get these messages after we start our server:

Cool! We’ve successfully started our server and our database appears to be operational.

Setting Up Our Server to Accept JSON

In our same server.js file we want to tell Express that it should accept JSON. Lets put this line of code in between our ‘database is open’ line of code and the ‘listen on port 3000’ line:

db.once('open', () => console.log('connected to database'))

app.use(express.json())

app.listen(3005, () => console.log('server started'))

The .use is middleware that allows you to run code when the server gets a request but before it gets passed to your routes. So in this instance we’re telling Express to accept JSON as the data format.

Creating Our Routes Folder & File

Let’s create a new directory for our routes to live in called routes and then a file in this directory called subscribers.js . Inside of this file is where we will define how the server should handle the data when it receives a GET, POST or PATCH request.

But before we start creating those, lets switch back to our server.js file and tell the server that we now have routes that it needs to handle and use. These next two lines of code are actually the last ones we need for our server.js file so here’s the full file with the new lines highlighted:

require('dotenv').config()

const express = require('express')
const app = express()
const mongoose = require('mongoose')

mongoose.connect(process.env.DATABASE_URL, { useNewUrlParser: true })
const db = mongoose.connection
db.on('error', (error) => console.error(error))
db.once('open', () => console.log('connected to database'))

app.use(express.json())

const subscribersRouter = require('./routes/subscribers')
app.use('/subscribers', subscribersRouter)

app.listen(3005, () => console.log('server started'))

If something is missing or incorrect, right now is a great checkpoint to make sure you’ve got everything updated with the above. Give yourself a pat on the back for getting this far! We’re getting onto the fun stuff next…

Setting Up Our Routes

Now that our server file is all setup, let us now switch gears to our new subscribers.js routes file. To start, let us require Express and define the express.router() function on a variable called router . While we’re at it let’s add our module export function as well at the very bottom:

const express = require('express')
const router = express.Router()

module.exports = router

Before we get into the code, let’s get an understanding of what we exactly want to do with our routes. Since we’re trying to see and artificially create new subscribers on Youtube, we need this set of criteria:

  • Route for getting all subscribers
  • Route for getting one subscriber
  • Route for creating one subscriber
  • Route for updating one subscriber
  • Route for deleting one subscriber

Now let’s start each of the bullet points above with the basic framework depending on if its a GET, POST or PATCH request:

const express = require('express')
const router = express.Router()

// Get all subscribers
router.get('/', (req, res) => {
})

// Get one subscriber
router.get('/:id', (req, res) => {
})

// Create one subscriber
router.post('/', (req, res) => {
})

// Update one subscriber
router.patch('/:id', (req, res) => {
})

// Delete one subscriber
router.delete('/:id', (req, res) => {
})

module.exports = router

The GET, POST and DELETE methods should look familiar but if not here’s a little refresher on them . The one thing that might look weird is the PATCH method. The PATCH method is being used here instead of the more traditional PUT method because we only want to use this to update pieces of the subscriber’s information and not all the information of the subscriber.

You also may have noticed that we include /:id in most of our parameters. This is for the routes that are requesting an action to be taken on a single subscriber thus we need that subscriber’s unique ID.

Testing Out Our API

Let’s take a little break from our routes and test out our API with what we have so far. Inside of our ‘Get all subscribers’ route, let’s send text to our server:

// Get all subscribers

router.get('/', (req, res) => {
   res.send('Hello World')
})

Now for testing our API, I am going to use a Visual Studio Code extension called REST Client. If you do not have VS Code then you can use another program called Postman that will also aid in testing the API. For this tutorial I will be using just REST Client in VS Code.

Ok so once you have the REST Client extension installed, let’s create a new file in our routes folder for us to run our tests and call it route.rest. It needs to end in .rest or else it will not work correctly with REST Client.

Great so now let’s write a test GET call to our server inside of our route.rest file:

GET http://localhost:3000/subscribers

Make sure you have /subscribers after the 3000. Now if you hover above that line you just wrote, you should see ‘Send Request’ appear above it. Click that and watch on the right hand side of your screen for the result. If all went well, it should look something like this:

Hello World!

On line 9, we can see that the server sent back ‘hello world’. This means our API is working correctly! Ok so we’ve done a lot so far, let’s take a hydration break and then we’ll get started with models.

Making the Model

Let’s go ahead and setup our model and the schema inside of our model. A schema is how our app defines what the data looks like and also sets up the document in MongoDB. If that sounds confusing, it’ll make more sense once we see what’s going on.

Let’s first start by creating a new folder called models. Inside of this folder, let’s create a new file called subscriber.js. Notice how we’re naming this file ‘subscriber’ singular as opposed to our routes file which is ‘subscribers’ plural. The idea is that the model will handle how each and every subscriber, on an individual level, will look inside of our database. The ‘subscribers’ routes handles sometimes multiple subscribers requests such as Get All Subscribers route. It’s an important thing to mention as verbiage is important when naming files in projects.

In this new file, we want to first require Mongoose since we will be using their schema models:

const mongoose = require('mongoose')

After we require mongoose, we’ll start by defining our schema

const mongoose = require('mongoose')

const subscriberSchema = new mongoose.Schema({})

Inside of this javascript object will be all of the keys for the different properties of our subscriber. These keys will include name, subscribedChannel and subscribeDate. We essentially want to tell our database what to expect from each one of these key’s such as their type, if they’re required and if a default value should be applied.

const mongoose = require('mongoose')

const subscriberSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true
  },
  subscribedChannel: {
    type: String,
    required: true
  },
  subscribeDate: {
    type: Date,
    required: true,
    default: Date.now
  }
})

The type and required properties should be pretty self explanatory. These are defining the expected schema type (a String and Date in this case) as well if that key is required upon entering information for a new subscriber.

One thing to note about subscribeDate, we set the type to Date instead of String since we will be expecting a date from the user. If no date is provided then we default it to the current date by using Date.now .

Ok so moving on, the last line of code we want to write in our schema is the module.exports. This will allow us to use and interact with the database using our schema. Mongoose has a special way of exporting models utilizing mongoose.model() that takes two properties:

// exporting our subscriber schema

module.exports = mongoose.model('Subscriber', subscriberSchema)

‘Subscriber’ is the name we want to give the model in our database and then the next one is the schema that corresponds to that model which is our subscriberSchema.

That’s it for our model! Let’s take a look at the finished schema to make sure we’ve got it all:

const mongoose = require('mongoose')

const subscriberSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true
  },
  subscribedChannel: {
    type: String,
    required: true
  },
  subscribeDate: {
    type: Date,
    required: true,
    default: Date.now
  }
})

module.exports = mongoose.model('Subscriber', subscriberSchema)

Routes – Create and Get Subscribers

Now that we have our model setup with a schema for our database, let’s require it in our subscribers.js route file below where we required router

const express = require('express')
const router = express.Router()
const Subscriber = require('../models/subscriber')

Now we can pick up where we left off with our routes where we coded a shell for each one:

// Getting all subscribers
router.get('/', (req, res) => {
   res.send('Hello World')
})

// Getting one subscriber
router.get('/:id', (req, res) => {
})

// Creating one subscriber
router.post('/', (req, res) => {
})

// Updating one subscriber
router.patch('/:id', (req, res) => {
})

// Deleting one subscriber
router.delete('/:id', (req, res) => {
})

We have our test response from earlier when we sent ‘Hello World’ to the server but we can go ahead and delete that since we want to actually tell that route to Get All Subscribers.

The first thing we’ll need to do, after we get rid of our old res.send('Hello World') line, is wrap the function in a promise with a try/catch statement:

// Get all subscribers

router.get('/', async (req, res) => {
  try {

  } catch () {

  }
})

Inside of our try statement we want to get all of the subscribers from our model. So we want to set a new variable called subscribers to that model with a .find() method applied to our Subscriber model.

// Get all subscribers

router.get('/', async (req, res) => {
  try {
    const subscribers = await Subscriber.find()
  } catch () {

  }
})

As the name implies, the find() Mongoose method works by returning all associated subscriber objects that meet its criteria. Since we’re returning all subscribers, we just leave the parentheses blank since we want all the subscribers:

After that line we then want to send a response with the data of our subscribers variable we just created in the form of JSON:

// Get all subscribers

router.get('/', async (req, res) => {
  try {
    const subscribers = await Subscriber.find()
    res.json(subscribers)
  } catch () {

  }
})

Finally, in our catch statement we want to just catch any errors that may occur and have it sent to the user as a 500 error in JSON format:

// Get all subscribers

router.get('/', async (req, res) => {
  try {
    const subscribers = await Subscriber.find()
    res.json(subscribers)
  } catch (err) {
    res.status(500).json({ message: err.message })
  }
})

Now that we have our route to send us all the subscribers in our database, we need to code a way for us to actually add a subscriber into our database. So, lets move onto our Create One Subscriber route so we can enter data about a subscriber:

// Create one subscriber

router.post('/', async (req, res) => {
  const subscriber = new Subscriber({
    name: req.body.name,
    subscribedChannel: req.body.subscribedChannel
  })

  try {
    const newSubscriber = await subscriber.save()
    res.status(201).json(newSubscriber)
  } catch (err) {
    res.status(400).json({ message: err.message })
  }
})

You can see its somewhat similar to our Get All Subscribers route except a few important differences. For one, we’re no longer doing a GET call on our database but a POST which will allow us to push data to our database on line 3.

On line 4 we are creating a variable that will be assigned to a new Subscriber from our model that we created earlier. If you recall, we require a name, subscribedChannel and subscribeDate properties for a new subscriber.

Line 5 and 6, we’re telling our route to save the request made from a user’s input of a new Subscriber name property and subscribedChannel property. Our subscribeDate doesn’t need to be defined because it will default automatically to the date/time that this database entry is made.

The try and catch statements should look familiar. We’re instead using a .save() Mongoose method instead of find() because this is how we will tell the database that we want it to hold the information a user passes to us through this router function.

Lastly, on line 10 we’re sending the user a response with a success status of 201 and to pass our new subscriber back to us as JSON. The catch is just like our Get All Subscribers route except we pass a 400 error since this would be a user error for passing us bad data.

Let’s Create and Get Our First Subscriber!

At this point we’ve created our Model and two Routes that will allow us to create a subscriber and then call that subscriber’s information from our database. Let’s switch gears back to our route.rest file and create our first user:

GET http://localhost:3000/subscribers

###

POST http://localhost:3000/subscribers
Content-Type: application/json

{
  "name": "Robert",
  "subscribedChannel": "Bennetts Channel"
}

With REST Client, we need to separate our different test requests with those three hashtags you see in between the two statements on line 3.

Our first request should be the exact same as before so the only different one here is our new POST request that allows us to create a new subscriber with their name (Robert in my case) and the channel they subscribed to (mine!). So lets run our POST request and see what we get:

Create Subscriber

If everything went well, our response when we click ‘Send Request’ should look like the above. We can see that we received our 201 success status at the very top along with our Subscriber object at the bottom with all the information we just plugged in.

Again, subscribeDate is set automatically to the date of creation so we don’t need to manually set it. Now lets use our Get All Subscribers request and make sure that it returns us Robert’s information:

Get All Subscribers

Our response will look similar to our Create Subscriber response since we only have a single user in our database but if you create multiple subscribers then this will populate all of them for you.

The Middle-what? The Middleware!

We’re in the final stretch! The last things few things we need to do is complete our Delete, Update and Get One Subscriber routes and our REST API is complete!

One thing in common that all 3 of the last routes share is getting the ID of a specific user. Instead of writing out that part of the code 3 times over we can just put that piece of code in its own function and call it as middleware in the Mongoose GET/PATCH/POST statements. Lets place this middleware function called getSubscriber right before our module.exports = router line:

async function getSubscriber(req, res, next) {
  try {
    subscriber = await Subscriber.findById(req.params.id)
    if (subscriber == null) {
      return res.status(404).json({ message: 'Cant find subscriber'})
    }
  } catch(err){
    return res.status(500).json({ message: err.message })
  }

  res.subscriber = subscriber
  next()
}

There’s a lot going on here so let’s break it down. The first line should look pretty familiar except that new property called next . Basically, when next is called its telling the function execution to move onto the next section of our code, which is the route function this getSubscriber function will be added to.

Our try and catch statements are opened up as with our other routes. We then define subscriber on line 3 equal to our Subscriber model object which we will then use the findById method to find our subscriber that correlates to the ID the user passes in from the parent route. This will set the subscriber to an object equal to that id.

Side Note: This part can be a little confusing but hang on until we get to the Update/Delete/Get One routes below. I’ll make more sense when we see it in action.

Once we have subscriber set to our model’s object, we check with an if statement to see if that subscriber even exists with a null check. If the subscriber is nonexistent then we want to throw a 404 error. Then our catch is doing the familiar error check and sending the user back a 500 status code if that

Finally we’re left with our last two lines of code from our middleware function:

 res.subscriber = subscriber
 next()

The res.subscriber is setting a variable on the response object which is equal to our subscriber object. This is useful so we don’t have to write that same line of code, we can just reference res.subscriber from this function. Lastly, we use the next() function after everything else is finished executing to tell the getSubscriber function to move onto the actual request.

Now that we’ve got our middleware function completed, let’s add it to our Delete, Update and Get One routes:

// Get one subscriber
router.get('/:id', getSubscriber, (req, res) => {
})

// Update one subscriber
router.patch('/:id', getSubscriber, async (req, res) => {
})

// Delete one subscriber
router.delete('/:id', getSubscriber, async (req, res) => {
})

Route – Get One Subscriber

We did most of the heavy lifting for these last 3 routes with our middleware so horray for that. Let’s start off with our Get One route:

// Get One Subscriber

router.get('/:id', getSubscriber, (req, res) => {
  res.json(res.subscriber)
})

Look how ridiculously simple that looks. All we have to do is send the user a response in JSON with the res.subscriber that we defined in our middleware function which returns that specific subscriber’s info. We can test this new route real quick to make sure our getSubscriber middleware function and this new route we created works.

Let’s hop back over to our route.rest file and create a new subscriber with our Create Subscriber request so we can get that subscriber’s ID:

Click to enlarge if you’re having trouble viewing

Alright so we created a new subscriber and named him Bob and we can see he has a long ID associated with his object right above his name. I want to keep that ID so when we write our new GET route I can call Bob specifically by his ID. We can put this below our Get All Subscribers request:

GET http://localhost:3000/subscribers

###

GET http://localhost:3000/subscribers/5d3ce4ef1b5de0b79d3443b9

###

POST http://localhost:3000/subscribers
Content-Type: application/json

{
  "name": "bob",
  "subscribedChannel": "Bennetts Channel"
}

On line 5 is where we’ll create the new test request, so put in your newly created user’s ID (yours will be different than mine above) and click ‘Send Request’:

If everything went well, we shouldn’t see a change on our response to the right because we’re just calling the same user that we just created. Give yourself a pat on the back, your middleware function and Get One route works!

Route – Delete Subscriber

Now that we know our middleware is doing its job, lets switch back on over to our subscribers.js routes file and finish our last two routes starting with Delete:

// Delete one subscriber

router.delete('/:id', getSubscriber, async (req, res) => {
  try {
    await res.subscriber.remove()
    res.json({ message: 'Deleted This Subscriber' })
  } catch(err) {
    res.status(500).json({ message: err.message })
  }
})

On line 4 we open up our try statement and then we plug in our await operator right before we set our res.subscriber to then use the remove() method to delete the subscriber that the res.subscriber object was set to. We then want to tell the user that we successfully deleted the subscriber on line 6. As always, we want our catch to send the user the appropriate error if one did occur. That’s it for delete!

Route – Update Subscriber

Our Update Subscriber route is the very last thing we need to write for this application to be fully functional! Ok so before we get into the code lets get a general idea of how updating will work in this case:

  • User updates just the name
  • User updates just the channel
  • User updates both name and channel
  • Or they mess up and it throws an error

Our requirements need for us to essentially check and see if any changes were made and if so, update them appropriately. Ok now onto the code:

// Update Subscriber

router.patch('/:id', getSubscriber, async (req, res) => {
  if (req.body.name != null) {
    res.subscriber.name = req.body.name
  }

  if (req.body.subscribedChannel != null) {
    res.subscriber.subscribedChannel = req.body.subscribedChannel
  }
  try {
    const updatedSubscriber = await res.subscriber.save()
    res.json(updatedSubscriber)
  } catch {
    res.status(400).json({ message: err.message })
  }

})

We start our function off with a PATCH method, which we discussed when initially defining the shell of our routes. Now you can see we’ve added two if statements to our function. The first if statement is checking to see if the name coming from the body of the user’s request is not equal to null. This is an important check because if it is equal to null then that means the user did not pass any data about name through our route function. If they did then we move onto line 5 where we’re setting our subscriber’s name from res.subscriber and setting the name now equal to the new name that the user passed in from their request.

The same logic follows on line 8 where we’re checking to see if the user updated the subscribedChannel and if so, we then perform the same sequence of changing the current subscribedChannel to the new one from the user’s request.

After we’ve made these if statement checks we then want to tell the function to then save these new changes into our database. This is easily done within our try statement where we take the res.subscriber object with our new name and/or channel and then add the save() method onto it within a new variable called updatedSubscriber. We then want to pass this new updatedSubscriber object to our user in the form of JSON.

That’s literally everything we need in our subscribers.js route file so let’s take a pause here and make sure we’ve got everything up to this point. Go to my github repo for this project and make sure your code accurately mirrors what I have before moving onto the final tests below.

The Final Test

We’ve completed our last two routes, let’s go into our route.rest file and test these bad boys out and make sure they work correctly.

Our Delete request is just as simple as our Get One Subscriber route except instead of using the GET request we’re naturally going to use the DELETE request instead. So get the ID of one of the subscribers in your database and let’s create that test route:

###

DELETE http://localhost:3000/subscribers/5d3e0db7cb4be0bfc4c25ff9

Now let’s click ‘Send Request’ and see if our user is successfully deleted:

Successfully deleted subscriber, Amy.

Nice! So we can see we got a message of ‘Deleted This Subscriber’ on the right hand side which means we were successful. Now if you take that same ID that you just deleted and try to request it using our Get One Subscriber request, it should tell us that it cannot find that subscriber since they no longer exist in our database:

Amy is no longer a subscriber, sad.

Our last request will be to update an existing subscriber’s information in our database with our Update route. Since we just deleted our last subscriber, go ahead and create a new subscriber and lets write our Update request using PATCH:

###

PATCH http://localhost:3000/subscribers/5d3e144ecb4be0bfc4c25ffa
Content-Type: application/json 

{
  "name": "Tommy"
}

I just created a new subscriber before running the above PATCH request and named them Lizzy:

Lizzy, my newest subscriber

Alright so if we run the above PATCH request we should see Lizzy’s name change to Tommy:

Lizzy decided her name sucks and now is named Tommy

If everything went smoothly then we just were able to successfully update Lizzy’s name to Tommy.

Conclusion

Guys, we made it. I really hope this tutorial was helpful to some of you. We went over a lot of stuff so if you’re feeling overwhelmed then thats totally understandable. But realize we just made a pretty awesome backend piece of code that translates into so many different real-world applications. So big props to you for making it through it all!

If you ever got stuck or found something worth mentioning, go ahead and leave me a comment below. Also feel free to follow me on Twitter and Youtube as I post regularly on both. Happy coding everyone!

Starting a Youtube Coding Series

After writing up my last tutorial on creating a horizontal scroll box , I started toying with the idea that creating a Youtube tutorial might be a bit quicker and easier way to approach coding tutorials. Written tutorials have their place but it honestly took me a lot longer to create than I anticipated. Personally, I learn a bit better through video tutorials anyways because watching someone’s flow just gives a bit better depth in understanding how to do something. I’m mostly doing this as a way for me to get better at certain areas of coding. Since teaching something requires a very solid grasp of the concepts, it’ll force me to learn something inside and out. I also think that if you figure something out that isn’t well documented on the web then it’s sort of a good way to give back to the community by showing your solution to the problem. Anyways, here’s a link to the intro video:

JavaScript: From Fundamentals to Functional JS V2- FEM Course Review

JavaScript: From Fundamentals to Functional JS - Course Review

I just finished Bianca Gandolfo’s ‘JavaScript: From Fundamentals to Functional JS, v2’ course on Front End Masters a couple weeks ago and figured I would give my two cents on the whole thing. Being its 8 hours long, not including the pausing you’ll do to practice code and jot down notes, having a good idea of what you’ll be presented with before plunging head first might give you an idea if its something worth investing the time in.

TLDR Version:

If you’re a beginner or intermediate javascript developer, this class from beginning to end is absolutely worth the time invested. With Bianca’s in-depth analysis of some more common JS fundamentals that we take for granted, you’ll certainly come out of it with a better understanding of the Javascript language as a whole. My only critique is that the more advanced concepts of functional programming like compose and currying seemed to be rushed without going into too many fundamental use cases. People looking for expanded explanations of functional JS programming concepts may not find this course as helpful. Although most JS devs probably do not fall into that category so it’s great for the majority of people.

Course Setup:

Starting out, Bianca sets the tone of her class by telling the students that they will be called on to participate and that the coding challenges will also offer ‘clues’ . These clues are apart of a murder mystery game that Bianca has structured her class around to make the coding concepts more engaging.

Both of these qualities, student participation and Clue, gave the course an interesting and entertaining aspect. I personally hated being called on during class to answer questions in front of everyone but in this instance it works very well as a 3rd party viewer. A lot of the questions that may have been otherwise glossed over by Bianca were revisited because someone was called on and didn’t understand a certain concept. This was a huge help for me because there was a handful of times I was royally lost and one of the students also had the same question I had when they were called on.

The Content:

You can take a look at the course syllabus but Im going to list out the subjects below that I felt a much better understanding of after this course:

  • Array destructuring
  • Map and filter methods (in depth)
  • Function declaration VS function expression
  • Scope walkthroughs
  • Callbacks
  • Closure

So one of my favorite parts of the whole course was the line-by-line walkthrough of Scope. I never really had a clear idea of how scope worked and seeing it thought out loud and talked about this way made concepts like Block Scope, Function Scope and Lexical Scope so much clearer.

Honestly the line-by-line code explanations in general was what made this class so special. She really took the time to make sure the whole class knew what was going on at a very basic level before proceeding. It also seemed like the majority of the people participating were in that beginner to intermediate category (just like me) so we were all somewhat on the same wavelength when thinking through these problems.

If you didn’t read the TLDR version I had above, I did mention that there seemed to be a lack of content for compose and currying. This is just from my perspective as a beginner to functional programming. Maybe in reality those functional techniques aren’t really used that widely which is why they were glossed over, but either way I sort of left those lessons with a barebones idea of what they were.

And the killer is….

Well you’ll have to take the course and get to the end to find that out. All in all Im very happy with the time I took with this course. It improved my understanding of some more basic JS fundamentals that I took for granted. If you’re someone who uses methods like map, filter and callbacks but really want to know whats going on under the hood then this course is right up your alley. You’ll also get a lot of interesting tidbits of info like … an array is actually just an object! That one might have been obvious to some but she sprinkles a lot of little interesting facts like that throughout the course.

Oh one last thing before I end this. Throughout the course I started using this organizational/note taking tool called Notion. This thing is great, its like a notepad that was specifically built for developers. You can embed code straight to your writing with auto syntax highlighting. You can even include a functional Codepen snippet into your document. Its just clean and really a joy to use. Thought I’d give those guys a shoutout as I’ll continue to use them for jotting down my notes from these courses on Front End Masters.

Create a Horizontal Mobile Scroll Box Using CSS Flexbox and Media Query

I had the chance to flex my CSS chops recently, which turned out to be pretty weak, but I learned a few cool things along the way. I was tasked to create a vertical list that transforms to horizontal scrolling when sized down to mobile. This was the outcome:

The two main takeaways from this came from using CSS’s media queries and flexbox. I had only done some real quick and dirty CSS styling in the past so this was my first exposure to both of these two tools. I whipped up this simple Codepen version of the above where you can see the vertical to horizontal list and scroll in action. The majority of the magic comes from this little chunk of CSS:

@media (max-width: 992px) {
  .container {
      display: flex;
      flex-wrap: nowrap;
      height: 300px;
      overflow-x: auto;
      width: auto;
  }
}

The first thing you’ll notice is that @media rule which is how Im telling the div with all the items to apply the subsequent CSS properties to the .container class. To put it simply, when the screen size hits 992px or lower, the .container class now changes/adds the listed properties starting with display: flex .

Next, we’re adding flexbox with display: flex and then making sure that the items do not wrap within the container as we scale it down with flex-wrap: nowrap . I changed the height of the container to a more narrow 300px so it creates a mobile-friendly view of the item that scroll.

Sidenote: If you’re unfamiliar with Flexbox , I highly recommend doing this interactive learning game: Flexbox Froggy . It teaches you most of the basic and some advanced properties of Flexbox by maneuvering a frog onto its lillypad.

Finally we add overflow-x: auto to allow the items within the container to have scrollable functionality on the X axis when the items spill outside of the parent container. Without this property we’d have something that looks like this:

🙁

Once we have all those properties put together, we’re left with a nifty little item list that transforms to mobile-friendly horizontal scrolling:

codepen scroll animation

Typically, you’re going to be taking a list of items that is horizontal in desktop screen sizes and then scaling it down to a vertical list when hitting mobile screens. So we’re essentially forcing the opposite to happen here which isn’t too common and why its sometimes hard to find a solution for it on places like Stackoverflow.

Hopefully you found this useful. If you know of a better way or some clever little tricks I missed please be sure to let me know!

Minimalism: A New Pursuit

Credit: https://unsplash.com/@emileseguin

I’ve never been one to acquire an abundance of things. I still drive the first car I’ve ever owned, a 1999 Toyota Camry. I’ve only had 4 phones total and tend to keep them for 4+ years. I play a lot of PC games with friends but I only upgrade my computer about once every 4-6 years. Im currently wearing a shirt I purchased back in 2009 when I used to work at Pac Sun, which says a lot about how much I care for fashion. I guess I have an innate trait to avoid buying things because I personally hate shopping for stuff. Although, I have gone through times where I find myself hoarding too many things which is usually when Im in the midst of a hobby. Even then, I tend to recognize my stupidity and get rid of the unnecessary items soon after.

For the longest time I figured this is how most people view their belongings but I realized Im in a small minority of people who have this sort of outlook. Some might identify this as minimalism, although Im not as disciplined as I’d like to be in that practice. The idea of minimalism has always interested me since I naturally align with some of its concepts. Essentially minimalism states that you should only own the things that bring value into your life. That statement is a little fuzzy because most people can quite easily make up values for almost everything they own which is a trap I fall into myself. For example, I had 3 cameras which all could be used for different purposes. So I said the values that they provided me are different modes and styles of shooting photos. Boom, values have been assigned so I can automatically keep all 3, right? Well, not really because even though I assigned a value to all 3 of those cameras I actually had very weak values and utility from 1 of those in particular. For me, this was pretty easy to see which of the cameras I needed to get rid of but for other people it can be really hard to figure out how to judge what items they should keep and what items they should get rid of.

Another issue I find myself and lots of others dealing with is the ‘I might need this some day’ trap. Yes there are many things in life you might need one day but the benefits of lugging around boxes full of old kitchen equipment, vintage gaming consoles and your forgotten hobby of crocheting isn’t worth it in most cases. Sure, you might catch the bug to knit a nice little sweater for your cat 2 years from now but it isn’t worth the mental weight of knowing you have dozens of boxes stuffed with old knick knacks that haven’t been touched in years. It goes a little deeper than just keeping boxes of things because a lot of people don’t mind storing stuff in their closets and attics since its out of sight, out of mind. The thing is, it actually is weighing on your mind just on a really low frequency. Every time you open your closest and see the pile of boxes, hoards of clothes and racks of shoes you are reminded of all these things. There’s something that can’t really be described with words until you give yourself that opportunity of freedom from your belongings. Its like taking a weight off your mind that you didn’t even know was there, its very much a freeing experience.

It is preoccupation with possession, more than anything else, that prevents men from living freely and nobly.

Bertrand Russell

All this got me thinking about ways I could help rid myself of stuff I don’t care much for in my own life but also how I can help other people see their belongings in a different light. When I started my recent minimizing practice, I would go through all my stuff and write down on a sheet of paper the things I was on the fence about. I then looked at each item on paper and rated it on a ‘happiness’ scale between 1 and 10. Once I was done with this I grouped all the items below a 6 and decided that this would be the group of items I was going to get rid of. It was an eye opening experience because I never specifically dedicated much time to deciding how happy or useful an item I owned was using a scale system. This method really helped me hone in on the things that really didn’t matter to me which made the minimizing process of my belongings that much easier.

When I realized just how helpful this method was I figured it would be an amazing opportunity to create some new side project that I’ve been longing for since I got my new job as a developer. I got into programming to help people, thats my purpose with this pursuit, so it clicked almost instantly that this method could easily be translated into a web/mobile app. The general idea is that the application will get users to log items they’re unsure of and have them rate each of these items on a scale. The end ‘Results’ page will present a nice chart of sorts that gives people a visual representation of where all of their items landed on this scale helping them see from a higher level how they view each of those belongings. I love making sense of data so this will allow me to help others view how their belongings affect their lives from a different vantage point. Essentially this article was to state my idea for this new app since this is mostly a blog dedicated to my journey as a programmer. I also love delving into details of modern day materialism so I might be able to squeeze some extra features into this app as I go along with its development.

So this is my public declaration of commitment for building this new application. I’ve had it in my head for awhile and got the barebones started but its been on the back-burner for a few weeks now. Getting my thoughts down in writing helped streamline the concept so this blog post was super beneficial. I’ll be coming out with updates along the way as the development continues.