Using Template Engines

1. Setting View Engine

EngineSetup
EJSapp.set("view engine", "ejs")
Pugapp.set("view engine", "pug")
Handlebarsapp.engine("hbs", engine()) + app.set("view engine", "hbs")
Customapp.engine(ext, (path, opts, cb) => ...)

2. Configuring Views Directory

Example: Multiple view paths

app.set("views", [
  path.join(__dirname, "views"),
  path.join(__dirname, "shared/views")  // shared partials
]);

3. Rendering Templates

FormEffect
res.render(view)Render with locals only
res.render(view, locals)Pass data
res.render(view, locals, cb)Get HTML in callback (skip auto-send)
app.render(view, ...)Render without sending

4. Passing Data to Views

Example: Locals merging

app.locals.appName = "Acme";          // every render
res.locals.user = req.user;            // every render in this request
res.render("dashboard", { stats });   // template-specific
SourcePrecedence (lowest → highest)
app.locals1
res.locals2
render(view, locals)3

5. Using EJS Templates

Example: EJS syntax

<!-- views/profile.ejs -->
<%- include("partials/header") %>
<h1>Hello, <%= user.name %></h1>
<ul>
  <% for (const post of posts) { %>
    <li><%= post.title %></li>
  <% } %>
</ul>
TagPurpose
<%= %>Escaped output
<%- %>Raw HTML
<% %>JS control flow
<%# %>Comment

6. Using Pug Templates

Example: Pug indentation

doctype html
html
  head
    title= title
  body
    h1 Hello, #{user.name}
    ul
      each post in posts
        li= post.title
Pug FeatureDetail
Whitespace-significantIndentation = nesting
#{var}Interpolation (escaped)
!{var}Raw
extends layoutInheritance
block nameOverride-able sections

7. Using Handlebars

Example: express-handlebars setup

import { engine } from "express-handlebars";
app.engine("hbs", engine({
  extname: ".hbs",
  defaultLayout: "main",
  helpers: { uppercase: (s) => s.toUpperCase() }
}));
app.set("view engine", "hbs");
SyntaxPurpose
{{var}}Escaped output
{{{var}}}Raw HTML
{{#each}}Loop
{{#if}}/{{else}}Conditional
{{> partial}}Include partial

8. Creating Partials and Layouts

Example: EJS partial

<!-- views/partials/nav.ejs -->
<nav>
  <a href="/">Home</a>
  <% if (user) { %><a href="/logout">Logout</a><% } %>
</nav>

<!-- views/page.ejs -->
<%- include("partials/nav") %>
EngineLayout Mechanism
EJSexpress-ejs-layouts
PugBuilt-in extends/block
HandlebarsdefaultLayout option

9. Setting Global Template Variables

Example: app.locals helpers

app.locals.appName = "Acme";
app.locals.formatDate = (d) => new Intl.DateTimeFormat("en-US").format(d);
app.locals.currency = (n) => new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(n);

10. Using Helpers and Filters

EngineHelper Pattern
EJSFunctions on app.locals or passed in render
PugJS expressions inline; helpers via locals
Handlebarshelpers: { name: fn } in engine config
Warning: Never render user-controlled HTML with raw output (<%- %>, {{{ }}}) — XSS risk. Always escape unless you've sanitized.