Documentation Index Fetch the complete documentation index at: https://mintlify.com/expressjs/express/llms.txt
Use this file to discover all available pages before exploring further.
Template engines enable you to use static template files in your application. At runtime, the template engine replaces variables in a template file with actual values and transforms the template into an HTML file sent to the client.
Popular Template Engines
Pug Clean, whitespace-sensitive syntax
EJS Embedded JavaScript templates
Handlebars Minimal logic, mustache compatible
Setting Up a Template Engine
Install the template engine
Configure Express
const express = require ( 'express' );
const path = require ( 'path' );
const app = express ();
// Set views directory
app . set ( 'views' , path . join ( __dirname , 'views' ));
// Set view engine
app . set ( 'view engine' , 'ejs' );
Create template files
Create a file at views/index.ejs: <! DOCTYPE html >
< html >
< head >
< title > < %= title %> </ title >
</ head >
< body >
< h1 > < %= header %> </ h1 >
< ul >
< % users.forEach(function(user) { %>
< li > < %= user.name %> - < %= user.email %> </ li >
< % }); %>
</ ul >
</ body >
</ html >
Render the template
app . get ( '/' , function ( req , res ) {
res . render ( 'index' , {
title: 'My App' ,
header: 'Users' ,
users: [
{ name: 'Tobi' , email: 'tobi@example.com' },
{ name: 'Loki' , email: 'loki@example.com' }
]
});
});
EJS Templates
EJS (Embedded JavaScript) uses plain JavaScript in templates.
Basic Syntax
<!-- Output escaped value -->
< %= value %>
<!-- Output unescaped value -->
< %- value %>
<!-- JavaScript code -->
< % if (user) { %>
< h2 > Hello < %= user.name %> </ h2 >
< % } %>
<!-- Loop through array -->
< ul >
< % items.forEach(function(item) { %>
< li > < %= item %> </ li >
< % }); %>
</ ul >
Custom File Extensions
Register EJS with a custom extension:
const ejs = require ( 'ejs' );
// Use .html extension instead of .ejs
app . engine ( 'html' , ejs . __express );
app . set ( 'view engine' , 'html' );
// Now you can use .html files
res . render ( 'users.html' , { users: users });
The .html extension makes templates easier to edit in IDEs with HTML syntax highlighting.
Pug Templates
Pug (formerly Jade) uses indentation-based syntax.
Configure Express
app . set ( 'view engine' , 'pug' );
Create Pug template
Create views/index.pug: doctype html
html
head
title = title
body
h1 = header
ul
each user in users
li = user . name + ' - ' + user . email
Handlebars Templates
Handlebars provides minimal logic templates.
npm install express-handlebars
const exphbs = require ( 'express-handlebars' );
app . engine ( 'handlebars' , exphbs . engine ());
app . set ( 'view engine' , 'handlebars' );
<! DOCTYPE html >
< html >
< head >
< title > {{ title }} </ title >
</ head >
< body >
< h1 > {{ header }} </ h1 >
< ul >
{{ #each users }}
< li > {{ name }} - {{ email }} </ li >
{{ /each }}
</ ul >
</ body >
</ html >
Custom Template Engines
You can register custom template engines:
const fs = require ( 'fs' );
const marked = require ( 'marked' );
const escapeHtml = require ( 'escape-html' );
// Register .md as a template engine
app . engine ( 'md' , function ( path , options , fn ) {
fs . readFile ( path , 'utf8' , function ( err , str ) {
if ( err ) return fn ( err );
// Parse markdown and replace variables
const html = marked . parse ( str ). replace ( / \{ ( [ ^ } ] + ) \} / g , function ( _ , name ) {
return escapeHtml ( options [ name ] || '' );
});
fn ( null , html );
});
});
app . set ( 'view engine' , 'md' );
app . get ( '/' , function ( req , res ) {
res . render ( 'index' , { title: 'Markdown Example' });
});
Layouts and Partials
<!-- views/header.ejs -->
< header >
< h1 > < %= siteName %> </ h1 >
</ header >
<!-- views/index.ejs -->
< %- include('header', { siteName: 'My Site' }) %>
< main >
< p > Content here </ p >
</ main >
< %- include('footer') %>
//- views/layout.pug
doctype html
html
head
title = title
body
block content
//- views/index.pug
extends layout
block content
h1 Welcome
p This is the index page
Passing Data to Templates
// Pass individual values
res . render ( 'index' , {
title: 'My Page' ,
user: req . user
});
// Use res.locals for values available in all templates
app . use (( req , res , next ) => {
res . locals . siteName = 'My Website' ;
res . locals . currentUser = req . user ;
next ();
});
Use res.locals to set variables that should be available in all templates, such as the current user or site configuration.
Caching Templates
Enable view caching in production to improve performance:
if ( app . get ( 'env' ) === 'production' ) {
app . enable ( 'view cache' );
}
Best Practices
Escape user input to prevent XSS attacks
Use partials/includes for reusable components
Enable caching in production
Keep logic minimal in templates
Use layouts to avoid duplicating HTML structure
Set appropriate content type for non-HTML templates