Raddy Website Design & Development Tutorials

NodeJs Express EJS Layouts and Partials

By Raddy in NodeJs ·

Hello and Welcome! Today we are going to look at how we can use Express EJS Layouts to help us with website templating which ultimately help us to avoid writing duplicated code as well as making our website / application easily maintainable.

Normally you could use NodeJS for your backend application and use a front end development framework like Angular, VueJS, React, Svelte etc, but in this case for a quick NodeJS application, we could also just use a view engine like EJS. Of course, there are a lot of alternatives to EJS, but that’s one of the more popular options and that’s why we are going to use it.

Layouts & Partials Explanation

In general, our websites have more than one layout and often the only area of the website that needs to change drastically is the body. This is where EJS Layouts come in and help us create projects that are easier to maintain.

And for Partials, they are a common templating concept where the idea is to create reusable files that can be reused.

Project Structure

We will be making a two-page website which should be enough to get us started. The first page would be our home page (index.ejs) and that would be the page with the sidebar. The second page would be the About page (about.ejs) and that would take a full with.

šŸ“‚ node_modules
šŸ“‚ public
 šŸ“‚ css
  šŸ“œ main.css
šŸ“‚ views
 šŸŒ about.ejs
 šŸŒ index.ejs
 šŸ“‚ layouts
  šŸŒ full-width.ejs
  šŸŒ sidebar.ejs
 šŸ“‚ partials
  šŸŒ header.ejs
  šŸŒ footer.ejs
šŸ“œ README.md
šŸŒ app.js
šŸ“œ package-lock.json
šŸ“œ package-json

Install Packages

The packages that you need installed for your applications are EJS, Express and Express-Ejs-Layouts. I’ve also included Nodemon so I don’t have to restart the server every time I make changes.

Installing packages:

npm install ejs express express-ejs-layouts

Your package.json file should look similar to mine. Of course, you might have a newer version of the packages if you are doing this in the future.

{
  "name": "express-validator-tut",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "nodemon app.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "ejs": "^3.1.3",
    "express": "^4.17.1",
    "express-ejs-layouts": "^2.5.0"
  },
  "devDependencies": {
    "nodemon": "^2.0.4"
  }
}

The next step is to build our app. I won’t explain everything in detail, but I’ve added comments on every line and also I have a full video that can get you started with NodeJS, Express and EJS here.

Let’s build our app.js

// Imports
const express = require('express')
const expressLayouts = require('express-ejs-layouts')

const app = express()
const port = 5000

// Static Files
app.use(express.static('public'))
// Example for other folders - not required
// app.use('/css', express.static(__dirname + 'public/css'))

// Set Templating Engine
app.use(expressLayouts)
app.set('layout', './layouts/full-width')
app.set('view engine', 'ejs')

// Routes
app.get('', (req, res) => {
    res.render('index', { title: 'Home Page'})
})

app.get('/about', (req, res) => {
    res.render('about', { title: 'About Page', layout: './layouts/sidebar' })
})

// Listen on Port 5000
app.listen(port, () => console.info(`App listening on port ${port}`))

Layouts

Let’s start building our simple layouts and add some CSS to make them look slightly better. I avoided doing adding Bootstrap as it can look more complicated than it is.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><%- title %></title>
    <link rel="stylesheet" href="css/main.css">
</head>
<body>

    <div class="wrapper">
        <%- include('../partials/header.ejs') %>
        <main><%- body %></main>
        <%- include('../partials/footer.ejs') %>
    </div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><%- title %></title>
    <link rel="stylesheet" href="css/main.css">
</head>
<body>

    <div class="wrapper">
        <%- include('../partials/header.ejs') %>
        <div class="layout-sidebar">
            <main><%- body %></main>
            <side>Sidebar</side>
        </div>
        <%- include('../partials/footer.ejs') %>
    </div>

</body>
</html>

Main.CSS

As you can tell I didn’t waste too much time on the styles. Let’s just do something super basic:

body {
    background-color: #eee;
    font-size: 26px;
}

.wrapper {
    width: 700px;
    margin: 0 auto;
    background-color: #fff;
    padding: 10px;
}

header, footer {
    background-color: ghostwhite;
    padding: 20px;
}

main {
    background-color: cornsilk;
    padding: 20px;
}

.layout-sidebar {
    display: grid;
    gap: 10px;
    grid-template-columns: 2fr 1fr;
}

Now that we have the layouts and the CSS let’s add the partials:

<header>Header</header>
<footer>Ā© 2020 Raddy</footer>

Let’s build our pages. Index.ejs is our homepage and the about is the page that will be using the sidebar.

<p>This is the home page and it takes the full width of the layout</p>
<a href="/about">About</a>
<p>This is the about page. Look it has two columns.</p>
<p>This is a second paragraph and we can use normal html</p>
<a href="/">Home</a>
npm run start

Demo:

Thank you for reading this article. Please consider subscribing to my YouTube Channel.

More Resources:

  1. Shubham Nemade says:

    Error: Module “ejs” does not provide a view engine.

    1. Raddy says:

      Everything in the views folder needs to end with .ejs. I think that I might have messed up the folder structure on the article. I will update it in a second. If you go to the GitHub code you will see what I mean

  2. DemoMON says:

    if we have admin and use layout how to set them

    1. Raddy says:

      The same way you would do it for the front end. There shouldn’t be any difference

  3. Nitin Betharia says:

    Hi,

    How to implement a layout for the whole route? For Ex: The user route will have a different layout (so login, register, forget password etc) all will have the same layout, while the product route will have a different layout.

    I don’t want to set it with every render. Is it possible.

    Thanks in advance

    1. Raddy says:

      Hi Nitin,

      You could try to use URL params to determine which page you are on and then render it.


      app.get('/:page', (req, res) => {
      console.log(req.params.page);
      res.render('', { title: 'Home', layout: `./layouts/${req.params.page}` })
      })

      You would have to have a default value if the URL param is empty. Maybe use a Switch Statement and list your pages there.

Leave a Reply

Your email address will not be published. Required fields are marked *