DEV Community

Cover image for Create Templates in Node.js with Handlebar
Shayan
Shayan

Posted on

Create Templates in Node.js with Handlebar

Imagine you’re building a web application that sends personalized welcome emails to new users. Hardcoding the email content in your JavaScript files works for a small test, but as the user base grows, you need a way to manage dynamic content cleanly and efficiently. This is where Handlebars, a templating engine, comes in. It lets you define reusable templates and populate them with data, keeping your code organized and scalable. In this post, you’ll learn how to use Handlebars in Node.js to create templates, making tasks like generating HTML or text output straightforward and flexible.

Setting Up Handlebars in Node.js

To use Handlebars, you first need to integrate it into your Node.js project. Let’s walk through the setup process step by step.

Install Handlebars

Start by adding Handlebars to your project. Open your terminal and run:

npm install handlebars
Enter fullscreen mode Exit fullscreen mode

This installs the handlebars package, which provides the core functionality for creating and rendering templates.

Basic Project Structure

Create a simple project structure to work with. Here’s an example:

project/
├── templates/
│   └── welcome.hbs
├── index.js
└── package.json
Enter fullscreen mode Exit fullscreen mode

The templates folder will hold your Handlebars files (with a .hbs extension by convention), and index.js will contain the logic to render them.

Creating Your First Template

Handlebars templates are text files with placeholders for dynamic data. These placeholders, called expressions, use double curly braces like {{name}}. Let’s create a basic template.

Define the Template

In templates/welcome.hbs, add the following:

<h1>Welcome, {{name}}!</h1>
<p>Thanks for joining us on {{date}}.</p>
Enter fullscreen mode Exit fullscreen mode

Here, {{name}} and {{date}} are placeholders that will be replaced with actual values when the template is rendered.

Render the Template in Node.js

Now, let’s use Node.js to load and render this template. In index.js, write:

import fs from 'fs';
import handlebars from 'handlebars';

const templateString = fs.readFileSync('./templates/welcome.hbs', 'utf8');
const template = handlebars.compile(templateString);

const data = {
  name: 'Alex',
  date: 'February 24, 2025'
};

const output = template(data);
console.log(output);
Enter fullscreen mode Exit fullscreen mode

Run this with node index.js, and you’ll see:

<h1>Welcome, Alex!</h1>
<p>Thanks for joining us on February 24, 2025.</p>
Enter fullscreen mode Exit fullscreen mode

The compile function turns the template into a reusable function. You pass it an object (data), and it replaces the placeholders with the corresponding values. This approach keeps your presentation separate from your logic, making it easier to update designs or reuse templates.

Working with Helpers and Logic

Handlebars isn’t just about simple replacements—it also supports logic through built-in helpers and custom ones you can define. This adds flexibility to your templates.

Using Built-in Helpers

Handlebars provides helpers like if and each for conditional logic and loops. For example, imagine you want to list user interests if they exist. Update welcome.hbs:

<h1>Welcome, {{name}}!</h1>
{{#if interests}}
  <p>Your interests:</p>
  <ul>
    {{#each interests}}
      <li>{{this}}</li>
    {{/each}}
  </ul>
{{else}}
  <p>No interests listed yet.</p>
{{/if}}
Enter fullscreen mode Exit fullscreen mode

Then, in index.js, adjust the data:

const data = {
  name: 'Alex',
  interests: ['coding', 'reading', 'hiking']
};

const output = template(data);
console.log(output);
Enter fullscreen mode Exit fullscreen mode

This outputs:

<h1>Welcome, Alex!</h1>
<p>Your interests:</p>
<ul>
  <li>coding</li>
  <li>reading</li>
  <li>hiking</li>
</ul>
Enter fullscreen mode Exit fullscreen mode

The if helper checks if interests exists and has content, while each loops over the array, using this to reference each item.

Creating Custom Helpers

You can also define your own helpers. Suppose you want to capitalize the user’s name. In index.js, register a helper before compiling:

import fs from 'fs';
import handlebars from 'handlebars';

handlebars.registerHelper('capitalize', (str) => {
  return str.charAt(0).toUpperCase() + str.slice(1);
});

const templateString = fs.readFileSync('./templates/welcome.hbs', 'utf8');
const template = handlebars.compile(templateString);

const data = { name: 'alex' };
const output = template(data);
console.log(output);
Enter fullscreen mode Exit fullscreen mode

Update welcome.hbs to use it:

<h1>Welcome, {{capitalize name}}!</h1>
Enter fullscreen mode Exit fullscreen mode

Output:

<h1>Welcome, Alex!</h1>
Enter fullscreen mode Exit fullscreen mode

Custom helpers let you extend Handlebars to fit your needs, keeping templates clean while handling complex formatting in code.

Integrating with Express

For web developers, Handlebars pairs well with Express, a popular Node.js framework. Here’s how to set it up.

Install Express and Handlebars for Express

Run:

npm install express express-handlebars
Enter fullscreen mode Exit fullscreen mode

The express-handlebars package adapts Handlebars for Express.

Configure Express

In index.js, set up a basic server:

import express from 'express';
import { engine } from 'express-handlebars';

const app = express();

app.engine('hbs', engine({ extname: '.hbs' }));
app.set('view engine', 'hbs');
app.set('views', './templates');

app.get('/', (req, res) => {
  res.render('welcome', { name: 'Alex' });
});

app.listen(3000, () => console.log('Server running on port 3000'));
Enter fullscreen mode Exit fullscreen mode

Place welcome.hbs in the templates folder as before. Visiting http://localhost:3000 renders the template directly in the browser. The res.render method compiles and sends the template with the provided data, streamlining web development.

Note: Set extname: '.hbs' in the engine options to match your file extension, as Express defaults to .handlebars.

Conclusion

As you can see, Handlebars makes it very easy to manage dynamic content for things like emails, HTML pages, or other text-based outputs. It also makes it easier to maintain and update content by separating the template from the logic.

I hope you found this article helpful. If you have any questions, please feel free to ask in the comments section below.

Top comments (0)