Express.js Templating Engines
# Express.js Templating Engines
Welcome to Chapter 17! In the last chapter, we served static HTML files. The problem with static HTML is that it's exactly the same for every user.
If John logs in, he should see <h1>Welcome John</h1>. If Sarah logs in, she should see <h1>Welcome Sarah</h1>. You cannot achieve this with a static .html file. We need a way to combine HTML with backend JavaScript data *before* sending it to the user. To do this, we use a Templating Engine.
---
1. Introduction
A Templating Engine allows you to write HTML templates that contain special placeholder syntax.
When a user requests a page, Express takes the template, injects your backend data (like a username from the database) into the placeholders, and "renders" a final, standard HTML string that it sends to the browser.
There are many engines available (Pug, Handlebars, Nunjucks), but EJS (Embedded JavaScript) is the most popular for beginners because its syntax is almost exactly like standard HTML, just with some JavaScript tags thrown in.
---
2. Learning Objectives
By the end of this chapter, you will be able to:
- Install and configure EJS in an Express application.
-
Create dynamic templates in the
viewsdirectory.
-
Use
res.render()to serve templates to the client.
-
Inject variables into an EJS template (
<%= %>).
-
Write logic (loops and if statements) inside an EJS template (
<% %>).
- Pass complex arrays and objects to the frontend.
---
3. Beginner-Friendly Explanations
How EJS Works
EJS stands for Embedded JavaScript. It uses special tags:-
<%= value %>: The equal sign=means "evaluate this JavaScript and print the result into the HTML." Use this for variables.
-
<% if(user) { %>: The lack of an equal sign means "run this JavaScript logic, but do not print anything." Use this forifstatements andforloops.
The views Folder
Express has a convention: it looks for all your template files inside a folder named views. EJS files use the .ejs file extension instead of .html.
---
4. Syntax Explanation
Let's set up EJS and render our first template.
Server Setup (app.js):
```javascript id="ch17-syntax-1"
const express = require('express');
const app = express();
// 1. Set EJS as the default templating engine app.set('view engine', 'ejs');
app.get('/', (req, res) => { // 2. We use res.render() instead of res.send() // It looks for a file named "index.ejs" in the "views" folder. // The second argument is an object containing the dynamic data. res.render('index', { username: "Alice_99" }); });
app.listen(3000);
html id="ch17-syntax-2" <!-- Standard HTML --> <html> <body> <!-- The EJS tag will be replaced by the value of username --> <h1>Welcome back, <%= username %>!</h1> </body> </html>
bash id="ch17-bash-1" npm install ejs
javascript id="ch17-code-1" app.get('/dashboard', (req, res) => { res.render('dashboard', { isLoggedIn: true, name: "Bob" }); });
html id="ch17-code-2" <% if (isLoggedIn) { %> <h2>Hello <%= name %>, here is your private data!</h2> <% } else { %> <h2>Please log in to view this page.</h2> <% } %>
javascript id="ch17-code-3" app.get('/store', (req, res) => { const products = [ { name: "Laptop", price: 999 }, { name: "Mouse", price: 25 }, { name: "Keyboard", price: 75 } ]; res.render('store', { items: products }); });
html id="ch17-code-4" <h1>Our Products</h1> <ul> <% items.forEach(product => { %> <li> <strong><%= product.name %></strong> - $<%= product.price %> </li> <% }) %> </ul>
bash npm init -y npm install express ejs mkdir views mkdir public
css body { font-family: Arial; padding: 20px; background: #f4f4f4; } .article-card { background: white; padding: 15px; margin-bottom: 10px; border-radius: 5px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); } .author { color: gray; font-size: 0.9em; }
javascript id="ch17-mini-project-1" const express = require('express'); const app = express();
app.set('view engine', 'ejs'); app.use(express.static('public')); // Serve CSS
// Mock Database const blogPosts = [ { title: "Learning Node.js", author: "Jane Doe", date: "Oct 10", content: "Node is awesome!" }, { title: "Express Routing", author: "John Smith", date: "Oct 12", content: "Routing is easy." }, { title: "Why I love EJS", author: "Jane Doe", date: "Oct 15", content: "Dynamic HTML is great." } ];
app.get('/', (req, res) => { res.render('home', { posts: blogPosts, title: "My Tech Blog" }); });
app.listen(3000, () => console.log('Blog running on port 3000'));
html id="ch17-mini-project-2"
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel="stylesheet" href="/style.css">
</head>
<body>
<h1><%= title %></h1>
<% if (posts.length === 0) { %>
<p>No posts available at this time.</p>
<% } else { %>
<!-- Loop through posts -->
<% posts.forEach(post => { %>
<div class="article-card">
<h2><%= post.title %></h2>
<p class="author">By <%= post.author %> on <%= post.date %></p>
<p><%= post.content %></p>
</div>
<% }) %>
<% } %>
</body>
</html>
``
Run it:
node app.js -> Visit localhost:3000
---
12. Coding Challenges
Challenge 1: Modify the blog project. Add a new route /post/:id. When the user visits /post/0, it should pass *only* blogPosts[0] to a new template called singlePost.ejs to render a full-page view of just that one article.
Challenge 2: Explore EJS Partials. Create a folder views/partials. Create a file header.ejs containing the <!DOCTYPE html>... tags, and include it at the top of your home.ejs file.
---
13. MCQs with Answers
Q1: What is the primary purpose of a Templating Engine? A) To write CSS faster. B) To connect to a database securely. C) To inject dynamic server-side data into HTML pages before sending them to the client. D) To serve static files like images. Answer: C
Q2: Which method is used to send a template to the browser?
A) res.sendTemplate()
B) res.html()
C) res.render()
D) res.sendFile()
Answer: C
Q3: Which EJS tag is used to OUTPUT a variable into the HTML?
A) <% variable %>
B) <%= variable %>
C) {{ variable }}
D) <%- variable %>
Answer: B
Q4: By default, which directory does Express look in to find your EJS templates?
A) /public
B) /templates
C) /pages
D) /views
Answer: D
---
14. Interview Questions
- 1. How does Server-Side Rendering (SSR) with engines like EJS differ from Client-Side Rendering (like React)?
-
2.
What is the difference between <%= %>
and<% %>in EJS?
evaluates the JavaScript expression and outputs (prints) the result directly into the HTML document. <% %> executes JavaScript logic (like loops or conditionals) silently without outputting anything to the HTML.
---
15. FAQs
Q: Do I need to learn EJS if I already know React?
A: Knowing how to build a JSON API (which React consumes) is more critical today. However, understanding templating engines is essential for rendering server-side emails, generating PDFs, and working on older full-stack codebases.
Q: Can I use CSS inside an EJS file?
A: Yes! It works exactly like HTML. You can use
<style> tags, or preferably, link to an external stylesheet hosted in your public folder.
---
16. Summary
-
Templating Engines blend static HTML with dynamic backend data.
-
EJS is a popular engine configured via
app.set('view engine', 'ejs').
-
Templates must be stored in the
views directory.
-
Use
res.render('filename', { data }) to generate and send the page.
-
Use
<%= %> for printing variables, and <% %>` for logical control flow.
---
17. Next Chapter Recommendation
Templating engines are great, but the modern web runs on APIs. Frontend frameworks (React, Vue) and mobile apps (iOS, Android) don't want HTML templates; they want raw data. In Chapter 18: REST API Development with Express, we will pivot back to building APIs that respond with structured JSON data.