SyntaxStudy
Sign Up
Express.js Layouts and Partials with EJS
Express.js Beginner 1 min read

Layouts and Partials with EJS

EJS does not include a layout system out of the box, but the `express-ejs-layouts` package adds one with minimal configuration. Alternatively, you can manually use `<%- include('partials/header') %>` to compose pages from reusable fragments, which is straightforward and keeps dependencies minimal. Partials are simply EJS files that receive the parent template's local variables. This enables a shared navigation bar, footer, and `` block across all pages. For more advanced layout composition — where child templates define content blocks that the layout renders — packages like `express-art-template` or switching to Nunjucks give you a Jinja2-style `block`/`extends` system. Caching template compilation is enabled in production via `app.set('view cache', true)`, which is automatically active when `NODE_ENV=production`. In development, disable it so template changes take effect without restarting the server.
Example
// views/partials/header.ejs
// <header>
//   <nav><a href="/">Home</a> | <a href="/about">About</a></nav>
// </header>

// views/partials/footer.ejs
// <footer><p>&copy; 2025 <%= appName %></p></footer>

// views/layout.ejs (with express-ejs-layouts)
// <!DOCTYPE html>
// <html>
// <head><title><%= title %></title></head>
// <body>
//   <%- include('partials/header') %>
//   <%- body %>              ← injected by express-ejs-layouts
//   <%- include('partials/footer') %>
// </body></html>

const express      = require('express');
const ejsLayouts   = require('express-ejs-layouts');
const path         = require('path');
const app          = express();

app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
app.use(ejsLayouts);
app.set('layout', 'layout'); // default layout file

app.use((req, res, next) => {
    res.locals.appName = 'MySite';
    next();
});

app.get('/', (req, res) => {
    res.render('home', { title: 'Home Page' });
});

app.get('/about', (req, res) => {
    res.render('about', { title: 'About Us' });
});

app.listen(3000);