Structuring Pug Templates: Choosing Between Extends, Include, and Mixins
A technical guide on choosing between Pug's extends, include, and mixins for Node.js/Express applications to build maintainable, server-rendered layouts and components.
21 Dec 2025, 19:29 UTC

The Architecture Decision
When structuring server‑rendered views in Node.js, the primary challenge is managing repetition without creating a maintenance burden. Pug provides three distinct mechanisms for reuse. Because Pug compiles templates into JavaScript functions, there is no runtime performance difference between these methods; the decision is based entirely on the nature of the variation required.
This guide assumes the use of Pug 3.x and Express 4.x. Note that Pug was formerly known as Jade; avoid using the .jade extension in modern projects.
Reuse Mechanism Comparison
| Mechanism | Primary Use Case | Input Capability | Behavior |
|---|---|---|---|
extends / block | Page Layouts | None (Inheritance) | Child overrides parent regions |
include | Static Partials | None (Verbatim) | Inserts file content exactly as is |
mixin | UI Components | Arguments & Blocks | Reusable function‑like fragments |
Layouts via Inheritance (extends/block)
Template inheritance is designed for the “skeleton” of your application. A base layout defines the HTML structure and marks specific areas as block regions. Child templates then extend that base and provide the specific content for those blocks.
This is the only mechanism that allows a child to “reach back” and modify the parent. For example, a child page can append a specific JavaScript library to a block scripts region in the head of the document without replacing the global scripts already defined there.
Static Fragments via include
The include command is a simple compile‑time insertion. It takes a file and pastes its contents into the current template. Because it accepts no parameters, it is best suited for fragments that are identical across every page they appear on, such as a global footer or a navigation bar.
Parameterized Components via mixins
Mixins function like JavaScript functions for your HTML. They are the correct choice for UI elements that share a structure but differ in data—such as product cards, alert banners, or form inputs. Mixins can accept arguments and can also contain a block, allowing you to pass a custom chunk of HTML into the component’s body.
Implementation Example
The following example demonstrates a layout that uses a mixin for a reusable alert component and an include for a footer.
// layout.pug (The Base)
doctype html
html
head
title My App
block styles
body
block content
include footer.pug
// mixins.pug (The Component Library)
mixin alert(type, message)
div(class=`alert alert-${type}`)
p= message
block // Allows nested content inside the alert
// index.pug (The Page)
extends layout.pug
include mixins.pug
block content
h1 Welcome
+alert('danger', 'System Error!')
span This requires immediate attention.
Validation and Security
To verify the implementation, render the page via Express and inspect the source. Confirm that the +alert call produces the expected CSS classes and that the nested appears inside the alert div.
Security Check: When rendering dynamic data, always use #{variable} for buffered interpolation. This automatically HTML‑escapes the content. Avoid using !{variable} unless the content is trusted, as it outputs raw HTML and creates a Cross‑Site Scripting (XSS) vulnerability.
Operational Constraints
To optimize production performance, ensure the Express view cache is enabled. In production mode (NODE_ENV=production), Express caches the compiled Pug functions, preventing the server from reading and parsing the files from the disk on every request.
Maintenance Warning: Avoid deep inheritance chains (e.g., Page > SubLayout > BaseLayout > GlobalLayout). This makes it difficult to trace where a specific block is being defined or overridden. Keep your hierarchy shallow and use mixins for granular logic.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.