How to change default layout in express using handlebars?

From the handlebars readme:

There are two ways to set a default layout: configuring the view engine's defaultLayout property, or setting Express locals app.locals.layout.

The layout into which a view should be rendered can be overridden per-request by assigning a different value to the layout request local. The following will render the "home" view with no layout:

app.get('/', function (req, res, next) {
   res.render('home', {layout: false});
});

In case you want to set the default layout just for a specific subroute, you might wanna use the following in the top section of your route:

router.all('/*', function (req, res, next) {
    req.app.locals.layout = 'admin'; // set your layout here
    next(); // pass control to the next handler
    });

You can also set the default layout on initialization:

// Create `ExpressHandlebars` instance with a default layout.
var hbs = exphbs.create({
    defaultLayout: 'main',
    helpers      : helpers,

    // Uses multiple partials dirs, templates in "shared/templates/" are shared
    // with the client-side of the app (see below).
    partialsDir: [
        'shared/templates/',
        'views/partials/'
        ]
    });

// Register `hbs` as our view engine using its bound `engine()` function.
app.engine('handlebars', hbs.engine);
app.set('view engine', 'handlebars');

I hope you are using express-handlebars. This instructions are for express-handlebars. For hbs, procedures are little different.

Step-1: Require handlebars

const exphbs = require('express-handlebars');

step-2: Register handlebars template engine. while registering, you can configure

for changing layout directory

const layoutPath = path.join(__dirname, './templates/layouts'); //you can build your desired path
app.engine('handlebars', exphbs({ layoutsDir: layoutPath }));

other available options along with layoutsDir are

interface ExphbsOptions {
    handlebars?: any;
    extname?: string;
    layoutsDir?: string;
    partialsDir?: any;
    defaultLayout?: string;
    helpers?: any;
    compilerOptions?: any;
}

step-3: If you want to change views directory

const viewPath = path.join(__dirname, './templates/views');
app.set('views', viewPath);

step-4: For some template, If you don't wish to give layout, you have to specify as layout: false . Otherwise app will crash. You can configure as follow, if you need.

app.get('/', (req, res, next) => {
    res.render('shop', { title: 'My Shop', layout: false })
});

For more info about express-handlebars


You can specify what layout you want to use as part of the render call. If you create a new layout called other.hbs, you can then do something like:

res.render('view', { title: 'my other page', layout: 'other' });

To override this for the entire application, you can use:

app.set('view options', { layout: 'other' });

This should work now..

npm install express-handlebars

.
├── app.js
└── views
    ├── home.handlebars
    └── layouts
        └── main.handlebars

2 directories, 3 files

app.js

var express = require('express');
var exphbs  = require('express-handlebars');

var app = express();

app.engine('handlebars', exphbs({defaultLayout: 'main'}));
app.set('view engine', 'handlebars');

app.get('/', function (req, res) {
    res.render('home');
});

app.listen(3000);

views/layouts/main.handlebars:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Example App</title>
</head>
<body>

    {{{body}}}

</body>
</html>