Skip to content

Route-Specific Layouts

The global layout configuration applies to every view by default. However, applications often require different structural frames for different contexts (e.g., a “Login” page without navigation vs. a “Dashboard” with a sidebar). You can override the default layout by passing a specific layout property during the render call.

In the res.render options object, the layout key specifies the path to the desired wrapper template.

// route using the sidebar layout
indexRouter.get("/dashboard", (req, res) => {
res.render("dashboard", {
title: "Mission Control",
layout: "layouts/sidebar",
});
});

Alternative layouts function exactly like the default one: they must include the <%- body %> placeholder to determine where the view content is injected.

File: views/layouts/sidebar.ejs

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title><%= title %></title>
</head>
<body>
<%- include("../partials/header.ejs", { title: title || "Dashboard" } ) %>
<div class="layout-sidebar">
<aside class="sidebar">
<h3>// System_Nav</h3>
<ul>
<li><a href="/dashboard">Overview</a></li>
<li><a href="/things">Inventory</a></li>
<li><a href="#">Analytics</a></li>
<li><a href="#">Settings</a></li>
<li><a href="/">Logout</a></li>
</ul>
<br />
<h3>// Server_Stats</h3>
<ul>
<li>Uptime: 99.9%</li>
<li>CPU: 12%</li>
<li>Memory: 450MB</li>
<li>Status: Online</li>
</ul>
</aside>
<main><%- body %></main>
</div>
<%# persistent footer %> <%- include("../partials/footer.ejs" ) %>
</body>
</html>

⏭ Global Locals

Available variables for every view, everywhere.