Sling Academy
Home/Node.js/Express + Handlebars + TypeScript: Tutorial & Examples

Express + Handlebars + TypeScript: Tutorial & Examples

Last updated: January 18, 2024

Introduction

Building web applications require a robust set of tools to handle the backend logic, templating for dynamically generating HTML, and a strong typed language for safe development practices. The combination of Express, Handlebars, and TypeScript offers a powerful stack for developers to build scalable and maintainable applications. In this tutorial, you will learn how to integrate Handlebars as a templating engine into an Express application that uses TypeScript.

Prerequisites

  • Basic knowledge of Node.js and Express
  • Familiarity with TypeScript
  • Node.js and npm installed
  • Visual Studio Code or your preferred IDE

Setting Up Your Project

First, create a new directory for your project and initialize a new npm package:

mkdir express-ts-handlebars

cd express-ts-handlebars

npm init -y

Install the necessary dependencies:

npm install express express-handlebars @types/express @types/express-handlebars typescript ts-node nodemon

Set up TypeScript in your project by creating a tsconfig.json file:

tsc --init

Edit your tsconfig.json to include the following options:

{
  "compilerOptions": {
    "target": "es2017",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true
  }
}

Integrating Handlebars with Express

To use Handlebars as your templating engine with Express, set it up in your entry file, typically this is index.ts:

import express from 'express';
import exphbs from 'express-handlebars';

const app = express();

app.engine('handlebars', exphbs());
app.set('view engine', 'handlebars');

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

app.listen(3000, () => {
  console.log('The web server has started on port 3000');
});

Then, create a views directory with a ‘home.handlebars’ file as a basic template:

<h1>Welcome to Express + Handlebars + TypeScript</h1>

Creating a Router and Controller

For more structure, you should create separate routers and controllers. Here’s a simple controller example:

export const homeController = (req, res) => {
  res.render('home', { layout: 'main', pageTitle: 'Home Page' });
};

And a router to match:

import { Router } from 'express';
import { homeController } from './controllers/homeController';

const router = Router();

router.get('/', homeController);

export default router;

Configuring the Layouts and Partials

In your views directory, create a ‘layouts’ directory with a main.layout.handlebars file:

<html>
  <head>
    <title>{{pageTitle}}</title>
  </head>
  <body>
    {{{body}}}
  </body>
</html>

Create partials for reusable components. For example, create a header.partial.handlebars file:

<header>
  <nav>
    <ul>
      <li><a href="/">Home</a></li>
    </ul>
  </nav>
</header>

TypeScript Typings

Handle request and response objects safely by extending the Express types:

import { Request, Response } from 'express';

interface TypedRequest<T> extends Request {
  body: T;
}

interface TypedResponse extends Response {
  locals: {
    user?: MyUserType;
  };
}

Complete Project Structure

Here’s how your project folder could look like:

express-ts-handlebars/
  ├─ src/
  │  ├─ controllers/
  │  │  └─ homeController.ts
  │  ├─ routes/
  │  │  └─ homeRoute.ts
  │  ├─ types/
  │  │  └─ custom.d.ts
  │  └─ index.ts
  ├─ views/
  │  ├─ layouts/
  │  │  └─ main.layout.handlebars
  │  ├─ partials/
  │  │  └─ header.partial.handlebars
  │  └─ home.handlebars
  ├─ package.json
  └─ tsconfig.json

Running the Application

Create a ‘start’ script in your package.json to compile and run your app:

"scripts": {
  "start": "tsc && node ./dist/index.js",
  "dev": "nodemon ./src/index.ts"
}

To start your application, run:

npm run start

Or for development with automatic reloading:

npm run dev

Conclusion

In this tutorial, you’ve learned how to integrate Handlebars as your templating engine into an Express application using TypeScript. Managing views is simplified, TypeScript brings strong typing to your app for better code integrity, and Express provides a lightweight framework to manage the web server and routing. With these tools, you can build efficient and effective web applications.

Next Article: Express + Handlebars: How to render a data table from an array

Previous Article: Express + Handlebars: Escaping Sensitive HTML Output & JavaScript

Series: Node.js & Express Tutorials

Node.js

You May Also Like

  • NestJS: How to create cursor-based pagination (2 examples)
  • Cursor-Based Pagination in SequelizeJS: Practical Examples
  • MongooseJS: Cursor-Based Pagination Examples
  • Node.js: How to get location from IP address (3 approaches)
  • SequelizeJS: How to reset auto-increment ID after deleting records
  • SequelizeJS: Grouping Results by Multiple Columns
  • NestJS: Using Faker.js to populate database (for testing)
  • NodeJS: Search and download images by keyword from Unsplash API
  • NestJS: Generate N random users using Faker.js
  • Sequelize Upsert: How to insert or update a record in one query
  • NodeJS: Declaring types when using dotenv with TypeScript
  • Using ExpressJS and Multer with TypeScript
  • NodeJS: Link to static assets (JS, CSS) in Pug templates
  • NodeJS: How to use mixins in Pug templates
  • NodeJS: Displaying images and links in Pug templates
  • ExpressJS + Pug: How to use loops to render array data
  • ExpressJS: Using MORGAN to Log HTTP Requests
  • NodeJS: Using express-fileupload to simply upload files
  • ExpressJS: How to render JSON in Pug templates