hapi — How to Use Multiple Handlebars Layouts

While running a website you’ll probably iterate on the design and functionality. Adding new pages is a good start to take a different path from your layout and apply new design ideas.

At Future Studio, we’ve applied a different design to the galaxy map, compared to other pages. Using layouts in handlebars simplifies this process a lot. This tutorial walks you through the hapi setup on how to use different handlebars layouts.

hapi Series Overview

View Rendering in hapi

To apply handlebars layouts in hapi, you need to set up view support in your application using the vision plugin. There’s a dedicated tutorial on how to render and reply views.

If you didn’t prepare your project for views yet, head over to the linked tutorial and move on once you’ve completed the setup.

The Single Layout Problem

While configuring the view support with server.views(config) in your project, you can specify a layout that will be used to render all your views. The setup in your project might look like this:

server.views({  
  engines: {
    html: require('handlebars')
  },
  layout: 'my-layout',
  path: Path.resolve('path/to/view/template/files')
})

With the layout: 'my-layout' property, you’re telling vision to use the my-layout file from within your views folder. The path to your view files is defined within path.

The problem with this setup is that vision uses my-layout for all pages that get rendered on server side. The next paragraph shows you how apply a different layout when using reply.view.

Using Multiple Handlebars Layouts

Let’s say your my-layout file specifies the layout for your site that is suitable for 80% of your web pages. It imports your header and footer, and keeps the content responsive using a CSS framework’s grid.

Within the rest 20% of pages you want to add a dedicated hero area with a gradient background and highlight a single element.

The requirements for sites with and without the hero area can be processed using two different layouts (with their custom placeholders and imports).

Well, hapi and especially vision allow you to define a different layout when rendering a view from your route handler:

hapi v17

server.route({  
  method: 'GET',
  path: '/second',
  handler: (request, h) => {
    return h.view('index', null, { layout: 'another-layout' })
  }
})

hapi v16

server.route({  
  method: 'GET',
  path: '/second',
  handler: (request, reply) => {
    reply.view('index', null, { layout: 'another-layout' })
  }
})

The short snippet above illustrates that reply.view allows three parameters:

  1. template: the template file name, located within the view’s path
  2. context data: (optional) used to render data into your view placeholders (e.g., {{tag}} in handlebars)
  3. options: (optional) view configuration object, used to override the server’s view manager configuration for this individual response

Almost all the view configuration options from vision are available, except isCached, partialsPath, and helpersPath. Everything else can be overridden for the view rendering process.

The route handler within the code snippet above overrides the layout property within the view configuration and instead defines another-layout to be used for this response.

That’s all the magic, awesome!

Outlook

This tutorial showed you how to benefit from multiple handlebars layouts within your hapi app. If you want to use different layouts throughout your website, make use of available view manager options for the view rendering process within route handlers.

Customize the rendering behavior with dedicated options and use the flexibility given by vision and hapi.

We’re happy to hear your thoughts and comments. Please don’t hesitate to use the comments below or find us on Twitter @futurestud_io. Let us know what you think!

Enjoy coding & make it rock!


Additional Resources

Explore the Library

Find interesting tutorials and solutions for your problems.