CodingNic

Server-Rendered Views

Partials and Layouts

Server-Rendered Views 10 min read

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:

text
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

html
<!-- views/partials/header.ejs -->
<header>
  <h1><%= siteName %></h1>
  <nav><a href="/">Home</a> | <a href="/about">About</a></nav>
</header>
html
<!-- views/partials/footer.ejs -->
<footer>
  <p>&copy; <%= 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

html
<!-- 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>
javascript
app.get('/with-partials', (req, res) => {
  res.render('page-with-partials', { siteName: 'DemoSite', year: 2026 });
});
bash
curl http://localhost:4104/with-partials
text
<!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>&copy; 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

  1. Create a partials/nav.ejs partial with a simple navigation menu, and include it in two different page templates.
  2. Pass a variable into the partial (like a “current page” name) and use it inside the partial to highlight the active link differently.
  3. Update the partial’s content once, and confirm the change appears on both pages that include it, without editing either page template directly.
  4. 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 partials subfolder.
  • <%- 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.