Express View Engines

A view engine (also called a template engine) lets you render dynamic HTML on the server. It combines a template file with data and produces HTML that is sent to the browser.

If you are building a REST API that returns JSON, you do not need a view engine. View engines are for traditional server-rendered web apps where the server produces the final HTML.

  • EJS : uses standard HTML with <%= %> tags for dynamic values
  • Pug : uses indentation-based syntax (no angle brackets)
  • Mustache : uses {{ }} syntax

This guide covers EJS because it uses familiar HTML with small additions, which makes it easier to read and learn.

Using EJS

Install

npm install ejs

Register the view engine

Tell Express to use EJS and where to find your templates:

const express = require('express');
const app = express();

app.set('view engine', 'ejs');
// By default, Express looks for templates in a 'views' folder

Create view files

Create a views/ folder and add .ejs files:

views/
  index.ejs
  about.ejs
  404.ejs

EJS files are regular HTML with optional template tags:

<h2>Homepage</h2>
<p>Hello, world</p>

Render a view

Use res.render() to render a template. Pass the template name without the .ejs extension:

const express = require('express');
const app = express();

app.listen(3000);

app.set('view engine', 'ejs');

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

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

// 404 handler: must be last
app.use((req, res) => {
  res.status(404).render('404');
});

Pass data to templates

Pass an object as the second argument to res.render(). Every key in the object becomes a variable available in the template.

app.get('/', (req, res) => {
  res.render('index', { title: 'Home' });
});

app.get('/about', (req, res) => {
  res.render('about', { title: 'About' });
});

app.use((req, res) => {
  res.status(404).render('404', { title: '404' });
});

In each template, output a variable with <%= variable %>:

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title><%= title %> | My Blog</title>
</head>

EJS syntax reference

PurposeTagDescription
JavaScript expressions<% (...) %>Run JavaScript (no output)
Output (escaped)<%= (...) %>Output a value, HTML-escaped
Output (unescaped)<%- (...) %>Output a value without escaping HTML
Comments<%# (...) %>EJS comment (not sent to browser)