|

Node.js Blog Tutorial

Nodejs Blog Tutorial

In this tutorial we are going to build a blog powered by Node.js on the back end, Bootstrap on the front end, and MongoDB as the data store. We are going to start from scratch and build out the project one step at a time. We’ll see how to include all the packages we’ll need into Node for building the blog. Some of these include Express, Bcrypt, nodemon, express-edge, mongoose, body-parser, express-fileupload, and express-session. We’ll start with basic routes in the index.js file, and then gradually move the application into a Model View Controller architecture. Let’s get started.


Setting Up The Blog Project

In our terminal, we can create our directory and run npm init to get started.

node $mkdir nodejs-blog-tutorial
node $cd nodejs-blog-tutorial
nodejs-blog-tutorial $npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See npm help json for definitive documentation on these fields
and exactly what they do.

Use npm install  afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (nodejs-blog-tutorial)
version: (1.0.0)
description: Create a blog using Node.js
entry point: (index.js)
test command:
git repository:
keywords: blog
author:
license: (ISC)
About to write to C:\node\nodejs-blog-tutorial\package.json:

{
  "name": "nodejs-blog-tutorial",
  "version": "1.0.0",
  "description": "Create a blog using Node.js",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "blog"
  ],
  "author": "",
  "license": "ISC"
}


Is this OK? (yes)

Excellent. Now, we will install a nice Bootstrap theme from the fine folks at Start Bootstrap.

nodejs-blog-tutorial $npm i startbootstrap-clean-blog
npm notice created a lockfile as package-lock.json. You should commit this file.npm WARN bootstrap@4.1.1 requires a peer of popper.js@^1.14.3 but none is installed. You must install peer dependencies yourself.
npm WARN nodejs-blog-tutorial@1.0.0 No repository field.

+ startbootstrap-clean-blog@4.1.1
added 4 packages from 10 contributors and audited 4 packages in 5.224s
found 0 vulnerabilities

Note that the package lives in the node_modules directory.
npm install startbootstrap-clean-blog

We are also going to need Express, so let’s go ahead and install it.

nodejs-blog-tutorial $npm i express
npm WARN bootstrap@4.1.1 requires a peer of popper.js@^1.14.3 but none is installed. You must install peer dependencies yourself.npm WARN nodejs-blog-tutorial@1.0.0 No repository field.

+ express@4.16.3
added 50 packages from 47 contributors and audited 123 packages in 4.111s
found 0 vulnerabilities

While we are at it, we can install nodemon for hot reloading of our JavaScript files. No need to constantly have to manually stop and re start your node application.

nodejs-blog-tutorial $npm i nodemon

Now let’s add the entry point to our node.js blog project which is index.js.

nodejs-blog-tutorial $touch index.js

We will also need to have a public directory in the project.

nodejs-blog-tutorial $mkdir public

Let’s get started by including express, setting up our public directory, and launching the server.


index.js


Building A Home Page

To get started building the home page, we can create a pages directory to store static files in. Within that directory we can start with an index.html file.

nodejs-blog-tutorial $mkdir pages
nodejs-blog-tutorial $cd pages
pages $touch index.html

Don’t get too excited, I know this home page is epic.


index.html

Let’s display that homepage in the browser now!


index.js

It’s Working!
blog home page

To make things look a lot better, we can copy the startbootstrap-clean-blog directory to the theme directory. The command line makes this fast and easy.

nodejs-blog-tutorial $cp -r node_modules/startbootstrap-clean-blog theme

Note the theme directory has everything we need to make this blog look great.
them folder to hold ui

Since we have set the public directory as where we will serve assets, we need to copy the vendor css img and js directories over. We also copy the theme index.html over to the pages directory.

nodejs-blog-tutorial $cp -r theme/vendor public/vendor
nodejs-blog-tutorial $cp -r theme/css public/css
nodejs-blog-tutorial $cp -r theme/img public/img
nodejs-blog-tutorial $cp -r theme/js public/js
nodejs-blog-tutorial $cp -r theme/index.html pages/index.html
nodejs-blog-tutorial $node index.js
App listening on port 4000

Once we launch the server, and load the home page – Wow! It looks pretty good!
start bootstrap clean blog


Adding About, Contact, and Post Pages

First we can copy about.html to our pages directory.

nodejs-blog-tutorial $cp -r theme/about.html pages/about.html

Now we can add a route handler to serve the requests to /about.


index.js

Go ahead and launch nodemon so the server will restart any time we change our files.

nodejs-blog-tutorial $nodemon index.js
[nodemon] 1.17.5[nodemon] to restart at any time, enter rs[nodemon] watching: *.*
[nodemon] starting node index.js
App listening on port 4000

There we go! A nice about page.
blog about page

We can do the same for contact and post pages.

nodejs-blog-tutorial $cp -r theme/contact.html pages/contact.html
nodejs-blog-tutorial $cp -r theme/post.html pages/post.html

Add the new route handlers for /contact and /post like so.


index.js

Bingo!
blog contact page

Excellent!
blog single post page


Edge Template Engine With Express

The pages so far are static. We want more of a dynamic situation. For this we can use the Edge Template Engine for use with Express.

nodejs-blog-tutorial $npm install express-edge --save

Here is how we can specify we are now using the Edge template engine in index.js.


index.js

Now let’s create the views directory which will hold our .edge files.

nodejs-blog-tutorial $mkdir views
nodejs-blog-tutorial $touch views/index.edge

In index.js, go ahead and remove this code.

Once the snippet above is removed, you can put this code in it’s place. This tells our application that we are now going to render an edge template named index from the views folder instead of our original static file.


Layouts With Edge

Just like all the other popular templating engines, we can set up layout files. Here we add a layouts directory within views, and add an app.edge file.

nodejs-blog-tutorial $mkdir views/layouts
nodejs-blog-tutorial $touch views/layouts/app.edge

In app.edge, we can add the common markup all pages will share. The “middle” of the page is removed and replaced with @!section('content').

Now we can really simplify any other files that extend the layout.app file. For example, now we can add this markup to index.edge.

Here is the result in the browser. Looks pretty good!
Edge Layout Example


Dynamic Data With MongoDB

Our Node js blog system is going to use MongoDB to store blog posts. The goal is to be able to store new blog posts into MongoDB, and also to retrieve blog posts from MongoDB and send that data to our .edge template files which will display the dynamic data. We can get started by installing Mongoose.

nodejs-blog-tutorial $npm i mongoose --save

Now we can require mongoose in our index.js file and connect to the database like we see here. Don’t forget the useNewUrlParser property.


Mongoose Models

We can create a dedicated directory to store our Mongoose Models and we’ll start with a Post.js file.

nodejs-blog-tutorial $mkdir database
nodejs-blog-tutorial $cd database
database $mkdir models
database $touch models/Post.js

Post.js will contain this code.


New Blog Post Form

Let’s add a page to the blog where a form is presented to the user so they can submit a new blog post.

nodejs-blog-tutorial $touch views/create.edge

The following markup can be put in the create.edge file.

Now we need a route in index.js to present the form.

Now we can visit http://localhost:4000/posts/new and we have a form for creating a new blog post.
new blog post form


Setting Up POST Requests in Express

Our form for a new blog post is going to send a POST request and we need to set up the code to handle that. We will also need the body-parser package to read the data that gets sent in the POST request. Let’s add body-parser first.

nodejs-blog-tutorial $npm install body-parser

Now we need to use body-parser in index.js. The relevant snippets are highlighted.

Now if you enter some data into the form, you’ll notice we can inspect it in the console if we submit the form. Nice!

[nodemon] starting node index.js
App listening on port 4000
{ title: 'This is the title field',
  description: 'Here is the description field',
  content: 'The content for the post is here' }

Store New Blog Post To MongoDB

Now that we are getting the data from the form we have to do something with it. We want to store it in the database. We will make use of the Post.js model we had created earlier.

Now we can update the /posts/store like so.

That should be enough to store a new post into the database. Go ahead and fill out the new blog post form, then click Submit. Then we can use Compass to check it out and our data is there.
node blog posts in compass


Displaying Blog Posts From The Database

Now we can remove the “static” pages that represented blog posts from before and use dynamic data from MongoDB to display blog posts. We can modify the / route to now fetch data from MongoDB. Then, we will pass that data to the index.edge file.

The index.edge file must now be fixed to account for dynamic data instead of the static markup we had before. We use the @each directive in Edge to do this. This allows us to loop over multiple blog posts stored in the database and display them.

We added a second blog post to the database, now let’s view the home page. Nice! We can see the title of two blog posts now thanks to our @each loop.
display multiple blog posts


Displaying a Single Blog Post

Now that we have the home page sorted which can display all posts, let’s set up the ability to click on a single post and view it’s contents. First off we need to modify the /post route to the following.

Now we must make the links clickable in the index.edge file so that we can click a title, and be brought to the single post view. Note the addition of the anchor tag which links to the unique post id of each blog post.

Now when we hover over the link on the main page, notice how the browser shows us that it is linking to the objectid of that blog post.
link to objectid of each blog post

Now let’s update the post.edge file to display the blog post dynamically.

Now we can easily click on any blog post title, and we are taken to that particular post to view it.
click objectid to visit blog post


Adding User Name and Created At To Blog Posts

Blog posts should have a user name associated with them, as well as a date of creating. We can update the Post.js model to reflect this.

We’ll need to adjust our create.edge file to accommodate for the user name.

Before we add any new blog posts, go ahead and drop the database from Mongo using the command line shell.

> mongo
> use node-blog
switched to db node-blog
> db.dropDatabase()
{ "dropped" : "node-blog", "ok" : 1 }
>

Now we can add some new blog posts to a fresh database by visiting http://localhost:4000/posts/new and if we check in Compass we can see the new properties in our database. Notice the createdAt and username properties.
new schema in the mongo database

We can update index.edge so that we can display this new data now.

Visiting the home page of the blog shows that these new properties are working great!
blog post-meta info

Let’s ensure post.edge is also now taking advantage of the post-meta information.

Looks Good!
post meta on single blog post page


How To Upload Images

Let’s add the ability to upload images when creating a new blog post. We can use the express-fileupload package to help us.

nodejs-blog-tutorial $npm install --save express-fileupload

We can add a field to add a new image when creating a post in create.edge.

We need to update the Post.js model to allow for our new image.

We need to make a few updates to index.js as well to handle image uploads.

We also need a directory to hold the images in.

nodejs-blog-tutorial $mkdir public/posts

Now if we create a new post and include an image, it gets stored in this directory.
image stored on the server

Now we can display that image in each post we create by updating post.edge.

When viewing this post now, it looks pretty cool with the background image set dynamically!
image upload used in blog post


Adding Simple Validation To Blog Post Creation

We do not yet have any way to validate data before we try to submit a post. Let’s add some middleware to help with this.

nodejs-blog-tutorial $mkdir middleware
nodejs-blog-tutorial $touch middleware/storePost.js

In the storePost.js file, we can add the most basic of validation. Basically, we just want all fields to be required. If any are missing, we just redirect back to the form.

Now, let’s use that middleware in index.js.

Great! Simple validation is now working.


Adding Controllers for a Model View Controller Application

Have you noticed that the index.js file is starting to become very bloated. This is not really ideal. We can fix this by restructuring the application to an MVC architecture. We can create the controllers directory and the controller files we need now.

nodejs-blog-tutorial $mkdir controllers
nodejs-blog-tutorial $touch controllers/createPost.js
nodejs-blog-tutorial $touch controllers/getPost.js
nodejs-blog-tutorial $touch controllers/homePage.js
nodejs-blog-tutorial $touch controllers/storePost.js

In those files will be this code.
createPost.js

getPost.js

homePage.js

storePost.js

With our controllers in place we can really simplify index.js now:

Ok! With MVC now in place, does the application still work? Let’s create a new blog post about Super Mario Bros.
new super mario blog post

Navigating to that new blog post shows us that all is still working great!
mvc blog in action


Adding User Registration

Let’s add the ability for a user to register to the site so they can post blogs. First we can create a new view file for that.

nodejs-blog-tutorial $touch views/register.edge

In register.edge we can add this markup.

Now let’s add a createUser.js controller and add the code we need.

nodejs-blog-tutorial $touch controllers/createUser.js

Finally, we can update index.js like so.

Now we need a User.js model to handle users.

nodejs-blog-tutorial $touch database/models/User.js

We also need a storeUser.js controller.

nodejs-blog-tutorial $touch controllers/storeUser.js

Now we can reference this new controller in index.js.

Ok with everything in place, let’s try to create a new user.
new user registration

Now we can use Mongo Compass to check and see if our new user is there. In fact, the user is there, so it looks like it is working great.
registered user in mongodb


Setting Up User Login

Since users are now able to register, we also need to give them the ability to log in. Let’s make a login.edge file first.

nodejs-blog-tutorial $touch views/login.edge

We can add this markup to login.edge.

Now we can create the login.js controller file.

nodejs-blog-tutorial $touch controllers/login.js

Here is the code for login.js.

Let’s make use of that new loginController in index.js

Just like that we have a nice login page now!
user login page


Handling the login POST request

The section above allows us to present a form to the user so they can type in their credentials. Now when they click the button to log in, we need to have the code in place to handle that POST request. First, we’ll create a loginUser.js controller and add some code.

nodejs-blog-tutorial $touch controllers/loginUser.js

Once again, we need to use this controller in index.js


Persisting Logins Using Sessions

All of the logic above works great, but the user is not persisted to a session just yet, let’s fix that now by installing express-session.

nodejs-blog-tutorial $npm install express-session

Next, add the express-session package to index.js.

We also want to use that package like so.

We need to adjust the loginUser.js controller to store the user’s session.

With our session now in place, we can put a check in our createPost.js controller. If the user is not logged in, we can redirect to the login page. We will only show the “Create new Post” page to a logged in user.


Storing Sessions In MongoDB

We can use the connect-mongo package to enable the ability to store sessions in the database. Let’s do that now.

nodejs-blog-tutorial $npm i connect-mongo

Once installed, we can update index.js like so.

Now when we log in, the session information is stored in MongoDB. In fact when we check our database in MongoDB using Compass, we can see that new sessions collection.
store session in mongodb


Set Up Authentication Middleware

We can protedct various pages or routes using middleware. Let’s create auth.js and add the needed code.

nodejs-blog-tutorial $touch middleware/auth.js

Now you can import that module into index.js and pass it as the second parameter to app.get(“/posts/new”, createPostController).


Flash Messages with connect-flash

Let’s see if we can set up flash messages for when a user tries to submit a form with errors. We’ll use the connect-flash package to do this. We an install it first.

nodejs-blog-tutorial $npm i connect-flash

Import into index.js using:

Then register it in index.js like this:

With connect-flash in place, we can now use it in the storeUser.js controller.

The createUser.js controller will need to be updated as well.

Lastly, in order to actually display these flash messages, we can update register.edge by adding this snippet just above the form.

Now, if a user makes a mistake during the registration process, the errors will be displayed just one time.
node connect-flash example


Preventing Authenticated Users From Visiting Register or Login Pages

Once a user is logged in, they no longer need to see the Register or Login pages. We can apply a middleware to enforce this.

nodejs-blog-tutorial $touch middleware/redirectIfAuthenticated.js

Now, all of the middleware in index.js can be updated like so.


Only Display Login and Register links to guests

We also need a way to conditionally show the login and register links based on if the user is logged in or not. First, update index.js like so.

In app.edge, we only show the login and register links if the user is not logged in.

Now, a guest will see the register and login links.
guest sees register and login links

The logged in user does not see those links.
logged in user does not see register or login links


Logging Out

First off, we can update the Nav area in app.edge like so.

Add this route to index.js.

Create the logout.js controller and add the needed code.

nodejs-blog-tutorial $touch controllers/logout.js

Make sure to import the logout controller like so.

This will allow the user to easily logout of the application.


Node.js Blog Tutorial Summary

That about sums it up for this tutorial on how to build a blog from scratch using Node.js and various packages from the NPM ecosystem. That’s for checking it out!

|