Create a Basic Framework with Express (Part 2)
Tags: node, handlebars, express
Published: 2023-05-01 02:15:27

In this part 2, we will define routes while incorporating Handlebars.

## Installing Handlebars

1. Install [express-handlebars](https://www.npmjs.com/package/express-handlebars) with the command
    
    ```bash
    npm install express-handlebars
    ```
    
2. Require `express-handlebars` in **index.js**
    
    ```javascript
    ...
    const app = express()
    const handlebars = require('express-handlebars')
    ...
    ```
    
3. Set the template engine in express
    - use **.hbs** file extension instead of **.handlebars**
    - default layout name as **app**
    - add helper functions for displaying full routes and env variable
        
    ```javascript
    ...
    app.engine(
        '.hbs',
        handlebars.engine({
            // use hbs instead of handlebars extension
            extname: '.hbs',
            // default layout name
            defaultLayout: 'app',
            // simple template functions
            helpers: {
                // return the full route path
                route(path) {
                    return process.env.APP_URL + ':' + process.env.APP_PORT + path
                },
                // returns the env variable value
                config(name) {
                    return process.env[name]
                },
            },
        })
    )
    app.set('view engine', '.hbs')
    // use views folder
    app.set('views', __dirname + '/views')
    // static folder
    app.use(express.static('public'))
    ...
    ```
        

## Create Views

1. Add `APP_URL` to **.env** file
    
    ```bash
    APP_URL=http://localhost
    ```
    
2. Create the main layout **app.hbs** in **views/layouts**
    - `route` helper function is used here to get the full path of the favicon
    - `config` helper function is used to get the env variable `APP_NAME`
        
    ```html
    <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <meta http-equiv="X-UA-Compatible" content="ie=edge">
            <link rel="icon" type="image/png" href="{{route  '/favicon.png' }}" />
            <title>{{config 'APP_NAME' }}</title>
            <script src="https://cdn.tailwindcss.com"></script>
        </head>
        <body class="bg-gray-100">
            {{{ body }}}
        </body>
    </html>
    ```
        
3. Add a favicon in the **public** folder named `favicon.png`
4. Create the homepage content **index.hbs** in **views** folder
    
    ```html
    <div class="min-h-screen flex flex-col">
        <div class="min-h-screen flex justify-center flex-wrap content-center">
            <div class="bg-gray-100 rounded-md w-10/12 md:w-1/2 lg:w-4/12 flex flex-col shadow">
                <div class="w-full p-8 flex flex-wrap content-center bg-white">
                    <div class="flex w-full justify-center">
                        <a href="{{route '/' }}">Homepage</a>
                    </div>
                </div>
            </div>
        </div>
    </div>
    ```
    

## Router

1. ***DELETE*** the following code since we will be adding controller and router files in **index.js**
    
    ```javascript
    ...
    const { ServerError } = require('./exceptions/ServerError')
    ...
    app.get('/', async (req, res, next) => {
        // res.send('Hello World!')
        try {
            // res.send('hello')
            throw new ServerError()
        } catch (error) {
            return next(error)
        }
    })
    ```
    
2. Create **index.js** in **routes** folder
    
    ```javascript
    const router = require('express').Router()
    
    // home page route
    router.get('/', async (req, res) => {
        // this will render the index.hbs with the default app.hbs layout
        return res.render('index')
    
        // to switch the layout file called main.hbs (make sure it is created in views/layouts)
        /**
        return res.render('index', {
            layout: 'main',
        })
        */
    })
    
    module.exports = router
    ```
    
3. Now to make sure the app knows to use the **routes/index.js**
    
    ```javascript
    ...
    app.use('/', routes)
    
    app.use(errorHandler.logger)
    ...
    ```