Partials and Layouts
Objectives
By the end of this lesson, you should be able to:
- Extract a reusable piece of a template into a partial
- Include a partial inside another template with
include() - Pass data into an included partial
๐ก Why this matters: A header and footer typically look identical on every page of a site. Copy-pasting the same HTML into every template means updating navigation links or a copyright year in a dozen places at once. Partials solve exactly this.
โ ๏ธ A note on verification: every snippet and every response shown below was actually run and tested with real HTTP requests.
Project File Structure
This lesson adds one new thing to the views folder established in Lesson 1, a partials subfolder:
project/
โโโ package.json
โโโ server.js
โโโ views/
โโโ partials/
โ โโโ header.ejs
โ โโโ footer.ejs
โโโ page-with-partials.ejs
Nothing about this structure is enforced by EJS itself, partials is a convention, not a requirement (unlike Handlebars’ views/partials, covered in Lesson 5, which auto-registers files found there), but it’s the standard way to keep reusable pieces separate from full pages at a glance.
Creating Partials
<!-- views/partials/header.ejs -->
<header>
<h1><%= siteName %></h1>
<nav><a href="/">Home</a> | <a href="/about">About</a></nav>
</header>
<!-- views/partials/footer.ejs -->
<footer>
<p>© <%= year %> <%= siteName %></p>
</footer>
A partial is just a regular .ejs file, nothing marks it as special except that it’s designed to be included inside other templates rather than rendered directly with res.render(). Keeping partials in a views/partials subfolder is a common convention, not a requirement.
Including a Partial
<!-- views/page-with-partials.ejs -->
<!DOCTYPE html>
<html>
<head><title><%= siteName %></title></head>
<body>
<%- include('partials/header', { siteName, year }) %>
<main>
<p>This is the main page content.</p>
</main>
<%- include('partials/footer', { siteName, year }) %>
</body>
</html>
app.get('/with-partials', (req, res) => {
res.render('page-with-partials', { siteName: 'DemoSite', year: 2026 });
});
curl http://localhost:4104/with-partials
<!DOCTYPE html>
<html>
<head><title>DemoSite</title></head>
<body>
<header>
<h1>DemoSite</h1>
<nav><a href="/">Home</a> | <a href="/about">About</a></nav>
</header>
<main>
<p>This is the main page content.</p>
</main>
<footer>
<p>© 2026 DemoSite</p>
</footer>
</body>
</html>
include(partialPath, data) renders another template and inserts its output at that point, include() is wrapped in <%- %> (Lesson 2), not <%= %>, because its result is already-rendered HTML, escaping it would print the actual <header> tags as visible text instead of rendering them. The second argument passes data through to the partial, { siteName, year } here uses the object shorthand (Module 2) to forward the outer template’s own local variables into the partial’s scope.
Why This Matters for Real Applications
Every page on a real site typically shares a header, footer, and often a navigation sidebar. Writing that HTML once as a partial, and including it everywhere, means a navigation link only needs updating in one file, not copy-pasted across every page. Module 10 (Project Structure & MVC) builds on this same idea for organizing a full application’s views.
Try It
- Create a
partials/nav.ejspartial with a simple navigation menu, and include it in two different page templates. - Pass a variable into the partial (like a “current page” name) and use it inside the partial to highlight the active link differently.
- Update the partial’s content once, and confirm the change appears on both pages that include it, without editing either page template directly.
- Explain, in your own words, why
include()is used with<%- %>rather than<%= %>.
Recap
- A partial is a regular template file designed to be reused, typically kept in a
partialssubfolder. <%- include('path/to/partial', data) %>renders a partial and inserts its output, unescaped, since it’s already HTML.- Extracting shared HTML (header, footer, navigation) into partials means updating it once, not on every page.
Next lesson: Handlebars, an alternative templating syntax with its own partials and layouts.