Adding templates to the mix

We now have a working site that has routes and middleware, but we are missing one import thing—HTML. Our requests come back with a Content-Type of text/html. Although res.send() adds this header for us, it is just text. It is missing a document type, head, and body, which is where another feature of Express comes in: templates.

We will use Embedded JavaScript (EJS) as our view template engine. I must notify you here that many tutorials, and even the Express command-line utility, default the view engine to Jade. I have used a few other template systems, which are not limited to PHP (which by itself is a kind of template system), Python's Django template, and Microsoft's Razor engine in MVC, to name a few. Luckily, EJS feels closer to all of these. I also feel that I don't need a parser to build my HTML. I want to write HTML and then add my variables where I need them. These are just a few reasons why we will continue using EJS.

Tip

If you like to use Jade, a major part of the application configuration will be the same. You will just have to build your own templates.

On a side note, I will reiterate that we don't want to install Express globally. You will see answers on Stack Overflow asking if the questioner has installed it locally or globally. Everything we need to do can be done locally. There is nothing that Express installed globally can do differently, where even the command-line utility works in this way:

 ./node_modules/.bin/express --help. 

We need to enable Express's view engine using the Express command app.set(). Before our middleware stack (app.use()), we should add the following:

app.set('view engine', 'ejs');
app.use(log.logger);
app.use(express.static(__dirname + '/static'));

To see a list of possible settings, visit two settings we are concerned with now are view engine and views. The views setting is used to set the view directory. By default, it is set to the views directory under the current directory. We will use the default value, so now we should create a directory named views. Our current folder structure should then look as shown in the following screenshot:

Under views, create a file named index.ejs and add the following HTML code to it:

<!DOCTYPE html>
<html>
<head>
  <title>Index</title>
</head>
<body>
Index
</body>
</html>

Following this, open up index.js from routes, and modify the index function as follows:

exports.index = function index(req, res){
  res.render('index');
};

Restart node and load the root. Alright, you now have a valid HTML5 document. Express knows to look in the views directory (views setting) for index.ejs (view engine setting). This is working great, but it is not very dynamic. We want to be able to change the response. We will need to modify the index.ejs file and change the head element, which you can do in the following way:

<head>
  <title><%= title %></title>
</head>

The main features we will use from EJS are <%= %>, which will output the value of the variable into the HTML document and <% %>, which allows us to execute JavaScript. Any if or for loop will also be used, in addition to any plain JavaScript.

Now, we have to pass a title variable to the view, so you can add the following code to the index function:

res.render('index', {title: 'Index'});

Browse to http://localhost:3000/, and you should see that the title of the tab is now Index. You can view the source of this page and see that it is rendered in HTML. This is great but not very maintainable. Essentially, this is no different than running a completely static website. So, we next need to add a layout.

Layouts

Express 3 lets each template-rendering library implement its own layout, which means it does not force any set way on the layout. This is different from Express 2 as it's defaulted to using a file named layout in the views directory. You will have to be careful that you do not get information about Express 2 when searching on the Internet. Our package of EJS does not have layout support, but we have already installed a package that does, which is express-partials.

We have to do a little setup to let Express know that we are using partials. The first step is to get a reference to our new library, which you can do by:

//all the other variables declarations at the top of app.js
var partials = require('express-partials');

Next, we add it as middleware. The only caveat here is that it has to be before our routes. This makes sense because we will have to render our complete page before the server sends a response.

app.use(partials());
//all other middleware functions

Finally, we can add a view option for the default layout.

//after variable declarations 
app.set('view options', {defaultLayout: 'layout'});
//but before the middleware

Setting the default layout is not required, but I will recommend it. Otherwise, we will have to define the layout for every view. We can override the default layout (or set it in the first place) using the render function:

res.render('index', {layout: 'layout', title: 'Index'});

Now that we have our layout setup, we can create it and update all our routes to use the layout. Create a file called layout.ejs in the views folder. Add the following code to it:

<!DOCTYPE html>
<html>
<head>
  <title><%= title %></title>
</head>
<body>
<%- body %>
</body>
</html>

Now, we can create two more files called login.ejs and chat.ejs. Finally, we have to update each res.render function to have the name of the file to render and a title.

exports.login = function chat(req, res){
  res.render('login', {title: 'Login'});
};
exports.chat = function chat(req, res){
  res.render('chat', {title: 'Chat'});
};

Now, all the routes will return valid HTML.

Let's go ahead and make our layout pretty. We will add the HTML code that our app will use, and the CSS framework we will be using is Bootstrap. It's great to get projects off the ground as we can start to be concerned with the code as opposed to the design. We will use a theme named Cosmo from Bootstrap site. We can get the CSS framework from http://bootswatch.com/cosmo/. Once you have downloaded the CSS file, create a new directory named css under the static directory. The path from root should be static/css/cosmo.min.css.

Tip

You can recognize Bootstrap sites as they have the same font, buttons, color, and CSS elements. If you are going to build something, you will want to differentiate it from other sites. You want users to associate with your site with just a look.

After carrying out all of these tasks, here is what our layout should look like:

<!DOCTYPE html>
<html>
<head>
    <title><%= title %></title>
    <link rel="stylesheet" href="css/cosmo.min.css">
</head>
<body>
<div class="container">
  <div class="row">
      <div class="col-sm-4"><h1>PacktChat</h1></div>
  </div>
  <div class="row">
  <%- body %>
  </div>
</div>
</body>
</html>

Refer to the following screenshot to see the index page in the new layout:

Tip

I recommend using Bootstrap when you start your projects. You can easily get a good-looking site without spending any time in design. Another great option is to use Zurb's Foundation. Using either of these frameworks is a good idea if you do not have much design experience. You can always go back and change the look.