Express + Handlebars + TypeScript: Tutorial & Examples

Updated: January 18, 2024 By: Guest Contributor Post a comment


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.


  • 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) => {

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:


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

      <li><a href="/">Home</a></li>

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:

  ├─ 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


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.