How to enable layout mode for Handlebars.js in Hapi.js

A couple of days ago I wrestled with this issue. I just wanted to enable a general layout.html file which other .html files could use as a basis. The issue had me stumped until I read the Hapi.js documentation (yeah, one should always read the docs):

vision includes built-in support for view layouts. It comes disabled by default, because it may conflict with other layout systems that specific view engines may provide. We recommend choosing only one layout system.

The fix was not to use the layout functionality but instead use handlebars’s {{> @partial-block }}, see the docs.

Working example #

Tested with Hapi.js version ^17.5.2.

Add this code to wherever you start the Hapi.js server:

const Hapi = require('hapi')

const init = async () => {
  const server = Hapi.server({
    port: 3000,
    host: 'localhost'
  })

  server.views({
    engines: {
      hbs: require('handlebars')
    },
    path: 'views',
    partialsPath: 'views/partials',
    relativeTo: __dirname,
    // nice trick to for quick local development without restarting server
    isCached: process.env.NODE_ENV !== 'test'
  })

  server.route({
    method: 'GET',
    path: '/',
    handler: (request, h) => h.view('index')
  })
}

// start the server
init()

Then you have a folder structure like so:

  • views/index.hbs
  • views/partials/layout.hbs

Within index.hbs #

{{#>layout}}
  Some main content.
{{/layout}}

Within layout.hbs #

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    {{> @partial-block }}
  </body>
</html>

There you go. :)