What Is Pug?
Pug is a template engine for server-side Node.js applications that enables dynamic HTML generation with clean, maintainable syntax. Formerly known as Jade (renamed in 2016 due to trademark issues), Pug transforms how developers create HTML templates by dramatically reducing boilerplate code while providing powerful features like template inheritance and reusable components.
Unlike traditional HTML that requires verbose opening and closing tags, Pug uses a whitespace-sensitive syntax where the tag name serves as the first element on a line, followed by the content. This approach results in templates that are easier to read, write, and maintain--particularly valuable for applications with dynamic content requirements.
Why Use Pug Over Plain HTML?
The advantages of using Pug extend beyond simple syntax reduction:
- Reduced syntax overhead - No closing tags means less typing and fewer opportunities for markup errors
- Built-in variable support - Native expression interpolation without external libraries
- Template inheritance - Create base layouts and extend them across your application
- Component reuse - Mixins enable reusable UI patterns without code duplication
- Native JavaScript expressions - Full access to JavaScript logic within templates
For server-rendered applications built with Node.js and Express, template engines like Pug enable developers to generate HTML programmatically while maintaining clean, maintainable codebases.
HTML vs Pug: Side-by-Side Comparison
The difference between traditional HTML and Pug becomes immediately apparent when comparing equivalent code. Pug's indentation-based syntax eliminates the need for closing tags while maintaining full semantic equivalence in the compiled output. This reduction in syntactic overhead translates to faster development cycles and fewer opportunities for markup errors.
Quick Reference: HTML to Pug Equivalents
| HTML Element | Pug Syntax | Notes |
|---|---|---|
<p class="container">Content</p> | p.container Content | Class shorthand uses dot notation |
<div id="header"><h1>Title</h1></div> | div#header: h1 Title | ID uses hash, colon enables sibling |
<a href="/" class="btn">Link</a> | a.btn(href='/') Link | Attributes in parentheses |
<span class="badge">New</span> | span.badge New | Inline content follows tag |
<ul><li>Item 1</li></ul> | ul: li Item 1 | Nested elements via indentation |
Complete Example: Document Structures
Traditional HTML markup requires explicit opening and closing tags for every element, leading to substantial visual noise in complex documents:
<!DOCTYPE html>
<html>
<head>
<title>My Page</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/css/main.css">
</head>
<body>
<div class="container">
<header>
<h1>Welcome</h1>
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav>
</header>
<main>
<section class="hero">
<h2>Getting Started</h2>
<p>This is a paragraph inside a container.</p>
</section>
</main>
</div>
<script src="/js/app.js"></script>
</body>
</html>
The equivalent Pug template achieves identical output with dramatically reduced visual complexity:
doctype html
html
head
title My Page
meta(charset='utf-8')
meta(name='viewport', content='width=device-width, initial-scale=1')
link(rel='stylesheet', href='/css/main.css')
body
.container
header
h1 Welcome
nav
ul
li: a(href='/') Home
li: a(href='/about') About
li: a(href='/contact') Contact
main
.hero
h2 Getting Started
p This is a paragraph inside a container.
script(src='/js/app.js')
Notice how Pug's syntax naturally mirrors the document structure through indentation, making the template's hierarchy immediately apparent without the cognitive overhead of matching opening and closing tags.
Clean Syntax
Tag-based markup without closing tags reduces boilerplate and improves readability
Template Inheritance
Extend base layouts and override blocks for consistent page structures across your application
Mixins
Create reusable component definitions for common UI patterns like buttons, cards, and form elements
JavaScript Integration
Use JavaScript expressions directly within templates for dynamic content rendering
Conditional Rendering
Control content display with if/else statements and boolean logic for personalized experiences
Iteration Support
Loop through arrays and objects with each and for constructs to render lists dynamically
Installing and Setting Up Pug
Installing Pug via npm
Getting started with Pug begins with a simple npm installation. Add Pug to your project dependencies with a single command:
npm install pug
This installation provides both the command-line compiler and the runtime API for integrating Pug into your Node.js applications. This straightforward approach makes Pug immediately accessible for any Node.js project, whether you're building a simple server or a complex enterprise application.
Setting Up Pug with Express
Integrating Pug with Express requires minimal configuration. Set the view engine and views directory in your Express application to enable automatic template rendering:
const path = require('path')
const express = require('express')
const app = express()
// Configure Express to use Pug as the view engine
app.set('view engine', 'pug')
app.set('views', path.join(__dirname, 'views'))
// Serve static files from the public directory
app.use(express.static(path.join(__dirname, 'public')))
// Example route that renders a Pug template
app.get('/', (req, res) => {
res.render('index', {
title: 'Welcome',
message: 'Building modern web applications'
})
})
app.listen(3000, () => {
console.log('Server running on http://localhost:3000')
})
The configuration shown here establishes the foundation for serving dynamic content. Express automatically compiles Pug templates when res.render() is called, eliminating the need for manual compilation steps. For applications built with our custom web development services, this integration pattern enables rapid prototyping while maintaining production-ready architecture.
Project Structure
Organizing your Pug templates in a consistent folder structure improves maintainability and team collaboration. The following structure separates layouts, partials, and page templates for clear organization:
project/
├── views/ # Pug template directory
│ ├── layouts/ # Base layout templates
│ │ ├── base.pug # Main application layout
│ │ └── admin.pug # Admin panel layout variant
│ ├── partials/ # Reusable template fragments
│ │ ├── header.pug # Navigation and branding
│ │ ├── footer.pug # Copyright and links
│ │ ├── sidebar.pug # Sidebar navigation
│ │ └── meta.pug # SEO meta tags
│ ├── components/ # Reusable UI components
│ │ ├── button.pug # Button mixins
│ │ ├── card.pug # Card component
│ │ └── modal.pug # Modal dialog
│ ├── index.pug # Home page template
│ ├── about.pug # About page template
│ └── contact.pug # Contact page template
├── public/ # Static assets
│ ├── css/ # Stylesheets
│ ├── js/ # JavaScript files
│ └── images/ # Image assets
└── app.js # Express application entry point
This structure supports template inheritance where pages extend base layouts, include shared partials like headers and footers, and leverage mixins defined in the components directory. For production deployments, consider enabling view caching through Express configuration to improve response times and reduce server load.
Pug Syntax Fundamentals
Basic Tag Syntax
Pug takes the tag name as the first thing in a line, and the rest is the content that goes inside it. This fundamental principle means every line begins with an element identifier, followed by either attributes in parentheses or content directly on the line:
// Simple paragraph element
p Hello from Pug
// Heading elements
h1 Welcome to My Website
h2 Subheading text
// Nested elements using indentation
div.container
h1 Page Title
p This is a paragraph inside a container.
.inner-content
p Nested paragraph with additional indentation.
The whitespace-sensitive structure means indentation level determines parent-child relationships. This eliminates the need for closing tags while preserving--and arguably improving--semantic clarity in complex document structures. Developers familiar with modern JavaScript development patterns often find this approach aligns naturally with their existing mental models of code organization.
Adding Attributes
Pug uses parentheses to define attributes on elements, following the tag name. Multiple attributes are separated by commas, and attribute values can use either single or double quotes:
// Link with href attribute
a(href='/about') About Us
// Image with multiple attributes
img(src='/image.jpg', alt='Product photo', class='responsive')
// Input with type, placeholder, and required attribute
input(type='email', placeholder='Enter your email', required)
// Button with multiple classes and data attributes
button(type='button', class='btn btn-primary', data-action='submit') Submit
// Script tag with source and integrity for security
script(src='/js/app.js', integrity='sha256-...')
IDs and Classes
Pug provides convenient shorthand syntax for id and class attributes using # and . notation respectively. This syntax mirrors CSS selectors, making it intuitive for developers familiar with styling:
// ID shorthand using # (equivalent to id="header")
#header
#main-content
// Class shorthand using . (equivalent to class="container")
.container
.content-wrapper
.card.primary
// Combining ID and class
div#app.container
// Element with ID and multiple classes
section#hero.hero-banner.highlighted
// Div is the default element when no tag is specified
.content
.sidebar
Text Content
Text in Pug can be placed inline after the tag or on subsequent indented lines for block text content:
// Inline text immediately after tag
p This is paragraph text.
h1 Heading text here
// Block text using indentation (preserves line breaks)
p
| This is block text
| that spans multiple lines
| and maintains the formatting.
// Text with variable interpolation
p Hello, #{userName}! Welcome back.
// Piped text within tags
div
| Regular text
span.highlighted And highlighted text
Mastering these fundamental syntax elements enables developers to write expressive, maintainable templates that clearly communicate document structure while minimizing syntactic noise.
Variables and Interpolation
Passing Variables from Express
Dynamic content in Pug templates comes from data passed during rendering. Express applications send data by providing an object as the second argument to res.render():
app.get('/dashboard', (req, res) => {
res.render('dashboard', {
user: {
name: 'Alex',
email: '[email protected]',
role: 'administrator'
},
stats: {
totalUsers: 1250,
activeSessions: 42
},
notifications: [
{ id: 1, message: 'New signup', read: false },
{ id: 2, message: 'Payment received', read: true }
],
timestamp: new Date().toISOString()
})
})
Interpolating Variables
Variable interpolation in Pug uses the #{variableName} syntax, allowing dynamic values to be embedded within text and attribute contexts:
// Simple variable interpolation in text
p Hello, #{user.name}!
// Interpolating in attribute values
img(src=user.avatarUrl, alt=user.name)
a(href=user.profileUrl) View #{user.name}'s profile
// Complex expressions within interpolation
p Total: #{items.length} items
p Discount: #{(originalPrice * discountRate).toFixed(2)}
// Ternary expressions
p Status: #{isActive ? 'Active' : 'Inactive'}
// Function calls with interpolation
p Generated: #{formatDate(timestamp)}
Function Results
JavaScript functions can be called directly within interpolation brackets, enabling sophisticated data transformation at render time:
// Calling a function passed from Express
p Current time: #{formatDate(timestamp)}
p Formatted currency: #{formatCurrency(amount)}
// Array methods within templates
p First item: #{items[0]}
p Last item: #{items[items.length - 1]}
// Object property access
p User role: #{user.role}
p Admin status: #{user.role === 'admin' ? 'Yes' : 'No'}
// Safe unescaped output with !=
- var htmlContent = '<strong>Bold text</strong>'
p!= htmlContent
Setting Variables in Templates
Variables can also be declared directly within Pug templates using the - prefix for JavaScript statements:
- var message = 'Hello from Pug'
- var count = 5
p #{message}
p Count: #{count}
- for (var i = 0; i < count; i++)
li Item #{i + 1}
- var isVisible = true
- if (isVisible)
.notification Notice message here
Understanding variable passing and interpolation is essential for building dynamic applications where content changes based on user data, database queries, or runtime conditions. This integration with JavaScript makes Pug particularly powerful for server-rendered applications built with our web development expertise.
CSS Integration
Link Stylesheets
Including external CSS files in Pug follows the same attribute syntax used for other HTML elements. The link element with rel="stylesheet" brings in your styling rules:
head
// Primary stylesheet
link(rel='stylesheet', href='/css/main.css')
// Responsive styles
link(rel='stylesheet', href='/css/responsive.css')
// Preconnect for faster font loading
link(rel='preconnect', href='https://fonts.googleapis.com')
link(href='https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap', rel='stylesheet')
// Conditional IE stylesheet
<!--[if IE 9]>
link(rel='stylesheet', href='/css/ie9.css')
<![endif]-->
Inline Styles
For critical CSS or small style blocks, use the style tag with piped text. This approach suits above-the-fold styles that should load immediately:
head
style.
.hero {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 4rem 2rem;
}
.notification {
background-color: #fff3cd;
padding: 1rem;
border-radius: 4px;
border-left: 4px solid #ffc107;
}
Best Practices for CSS in Pug
When integrating CSS with Pug templates, consider these established patterns for maintainable stylesheets:
- External stylesheets - Use for production code to enable browser caching and reduce page load times
- Critical CSS inline - Place essential styles inline in the head for improved first-contentful-paint
- Template inheritance - Define shared styles in base layouts that all pages extend
- Utility class integration - Leverage frameworks like Tailwind CSS directly within Pug class attributes
- Scoped styling - Consider CSS modules or BEM methodology to prevent style conflicts
// Example: Tailwind CSS integration with Pug
div(class='flex items-center justify-between p-4 bg-white shadow-md rounded-lg')
h1(class='text-xl font-semibold text-gray-800') Dashboard
button(class='px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700')
| Add New
// Example: Conditional classes for state-based styling
div(class=`alert ${isError ? 'alert-error' : 'alert-success'}`)
p= message
For applications built with our custom web development services, proper CSS architecture ensures maintainable stylesheets that scale with application complexity while maintaining fast page performance.
Control Flow in Pug
Conditionals
Conditional rendering in Pug uses familiar if, else if, and else statements. This enables content personalization based on user state, feature flags, or data conditions:
// Basic conditional rendering
if isLoggedIn
.welcome-message
p Welcome back, #{userName}!
a(href='/dashboard') Go to Dashboard
else
.login-prompt
p Please log in to continue.
a(href='/login') Log In
Else-if chains work seamlessly within Pug templates, supporting complex branching logic without nesting limitations:
// Multiple conditional branches
if user.role === 'admin'
.admin-panel
h2 Administrator Controls
a(href='/admin') Admin Dashboard
else if user.role === 'moderator'
.moderator-panel
h2 Moderator Tools
a(href='/mod') Moderation Queue
else if user.role === 'user'
.user-area
h2 Your Content
a(href='/my-posts') View Posts
else
.guest-area
p Please contact support for access.
Loops
For iterating over collections, for and each are interchangeable in Pug. This construct enables dynamic list rendering based on data arrays:
// Iterating over arrays with each
each product in ['Apple', 'Banana', 'Cherry']
li.product= product
// Accessing index during iteration
each item, index in items
li ##{index + 1}. #{item}
// Iterating over object key-value pairs
each value, key in {name: 'John', age: 30, city: 'NYC'}
p #{key}: #{value}
// For loops (equivalent to each)
for i in range(0, 5)
.box= i
While Loops
While loops generate repeated content based on a condition, useful when the iteration count is determined dynamically:
- var n = 0
ul
while n < 4
li Item #{n++}
// Practical example: pagination dots
- var currentPage = 3
.pagination
while i <= totalPages
.page(class={active: i === currentPage})= i++
Conditional Attributes
Boolean attributes and conditional class application enable dynamic element states:
// Boolean attributes (present when true, absent when false)
button(disabled=isSubmitting)
if isSubmitting
| Processing...
else
| Submit Form
// Input required attribute conditionally
input(type='email', name='email', required=isRequired)
// Multiple conditional classes using object syntax
div(class={active: isActive, 'has-error': hasError, 'is-loading': isLoading})
| Content
// Template literals for dynamic class combinations
div(class=`btn btn-${variant} btn-${size}`)
| Button Text
Control flow constructs transform static templates into dynamic, data-driven views that adapt to application state and user context.
Template Inheritance
Template inheritance represents Pug's most powerful feature for creating maintainable, consistent layouts across your application. Rather than duplicating header, footer, and navigation code in every page, inheritance enables single-definition reuse with selective overriding.
Extending Base Templates
A template extends another template using the extends keyword, inheriting all its structure while customizing specific regions:
layouts/base.pug (the parent template):
extends ../layouts/base.pug
Child pages simply specify the layout they extend, inheriting all defined blocks and structure.
Defining and Overriding Blocks
Blocks define named regions that child templates can override. This creates a contract between parent and child templates about customizable areas:
layouts/base.pug (base template):
doctype html
html
head
meta(charset='utf-8')
meta(name='viewport', content='width=device-width, initial-scale=1')
title= pageTitle || 'Default Title'
block head
// Child templates can add stylesheets or scripts here
body
header
include ../partials/navigation.pug
main
block content
// Default content if child doesn't override
p No content provided.
footer
include ../partials/footer.pug
block scripts
// Scripts can be added here
pages/about.pug (extending template):
extends ../layouts/base.pug
block head
title About Us | My Website
link(rel='stylesheet', href='/css/about.css')
block content
.about-page
h1 About Our Company
.about-content
p We build amazing web applications.
p Our team specializes in modern JavaScript technologies.
Including Partial Templates
Include directives bring other Pug files into the current template, enabling component decomposition:
// Include a navigation partial
include ../partials/navigation.pug
// Include a footer partial
include ../partials/footer.pug
// Include with local variable scope
- var showSocial = true
include ../partials/social-links.pug
// Include within a specific element
article.content
include ../partials/article-header.pug
.article-body
p Article content here.
Block Order and Placement
Blocks can be defined anywhere in templates and overridden in any order. Non-block content in the parent serves as defaults that child templates can completely replace or selectively preserve:
// layouts/base.pug - Base with multiple override points
doctype html
html
head
block meta
meta(name='description', content='Default description')
block title
title Default Title
body
.page-wrapper
block header
include partials/default-header
block main
main Default main content
block footer
include partials/default-footer
Template inheritance patterns work seamlessly with modern build tools and support team collaboration by establishing consistent page structures across your application.
Mixins: Reusable Components
Mixins in Pug function similarly to functions in programming languages--they define reusable component templates that accept parameters and generate consistent markup. This abstraction layer eliminates repetition for UI patterns used across multiple pages.
Defining Mixins
Create a mixin using the mixin keyword, specifying parameters that become dynamic values in the generated markup:
//- Mixin for a button component with variant support
mixin button(text, url, variant='primary')
a.btn(class=`btn-${variant}`)(href=url)= text
//- Mixin for a card component with optional image
mixin card(title, content, imageUrl=null)
.card
if imageUrl
.card-image
img(src=imageUrl, alt=title)
.card-body
h3.card-title= title
p.card-content= content
block
//- Mixin for form inputs with label
mixin input(label, name, type='text', required=false, placeholder='')
.form-group
label(for=name)
= label
if required
span.required *
input(type=type, name=name, id=name, required=required || null, placeholder=placeholder)
//- Mixin for alert messages
mixin alert(type, message)
.alert(class=`alert-${type}`)
= message
block
Using Mixins
Invoke mixins with the + prefix, passing arguments for each parameter defined in the mixin:
// Basic button usage with default variant
+button('Click Here', '/click')
+button('Learn More', '/learn', 'secondary')
// Button with all parameters
+button('Download PDF', '/download', 'success')
// Card with image
+card('Product Title', 'Product description here', '/images/product.jpg')
a(href='/products/1') View Details
// Card without image (third parameter is null)
+card('Service Name', 'Service description', null)
a(href='/services') Learn More
// Form inputs with various configurations
+input('Email Address', 'email', 'email', true, '[email protected]')
+input('Password', 'password', 'password', false)
+input('Phone', 'phone', 'tel')
// Alert mixin with additional content
+alert('success', 'Your changes have been saved.')
a(href='/continue') Continue
Mixin Best Practices
Establishing consistent patterns for mixin usage improves maintainability across your template codebase:
- Centralize mixins - Create a dedicated mixins.pug file included in your base layout
- Single responsibility - Keep each mixin focused on one UI pattern
- Parameter defaults - Provide sensible defaults for optional parameters
- Block support - Use
blockto accept content from callers for flexible composition - Documentation - Comment mixin parameters and expected values for team clarity
// mixins.pug - Central mixin definitions
include:markdown-it mixins/documentation.md
// In base layout
include mixins.pug
// Mixin file structure for large projects
// mixins/
// ├── buttons.pug
// ├── cards.pug
// ├── forms.pug
// ├── navigation.pug
// └── alerts.pug
Mixin patterns integrate naturally with modern frontend workflows and enable consistent UI development across your application's templates. For teams building complex applications, establishing a mixin library early pays dividends in development speed and code consistency.
Comments in Pug
Pug supports two types of comments: visible comments that appear in compiled HTML and invisible comments that are stripped during compilation. Understanding the distinction enables appropriate documentation strategies for both development notes and production output.
Visible Comments
Visible comments use the // syntax and appear in the compiled HTML output. These comments are accessible when viewing the page source in a browser:
// This comment will appear in the HTML output
//
Block comments
that span multiple lines
are also supported and will appear in HTML
// TODO: Refactor this section when implementing new design
.product-list
// Showing featured products only
.product Featured Product
Invisible Comments
Invisible comments use //- prefix and are stripped during the compilation process. These comments remain in source files but never reach the browser:
//- This comment will NOT appear in the compiled HTML
//- Use invisible comments for development notes
//-
Developer notes
that should not appear in production
keeping the output clean
.product-item
//- Temporary debug output
//- pre(style='display: none')= JSON.stringify(product)
Commenting Out Code
Prevent code from rendering while keeping it in source for reference or future reactivation:
//- This code is commented out completely
//- .old-section
//- h2 Old Content
//- p This won't render in the output
// Multi-line code comment
//-
.unused-component
h2 Removed Feature
p This section was temporarily disabled.
Practical Comment Patterns
//- ========================
//- Navigation Section
//- Main navigation across all pages
//- ========================
nav.main-nav
//- Links are dynamically generated from config
each link in navLinks
a(href=link.url)= link.text
//- @deprecated Use card-grid component instead
//- Old card implementation kept for migration
.card-wrapper
//- Migration note: Remove after Q2 refactor
Effective commenting practices support team collaboration and maintenance without cluttering production code with development notes.
Best Practices for Modern Pug Development
Organize Templates Effectively
Consistent organization ensures templates remain maintainable as applications grow:
- Semantic folder structure - Group related templates with clear naming conventions (layouts/, partials/, components/, pages/)
- Leverage inheritance - Create base layouts that establish common page structure, reducing duplication across templates
- Build reusable mixin libraries - Centralize UI component definitions for consistent styling and behavior
- Minimize template logic - Complex data transformations belong in JavaScript; templates should focus on presentation
Performance Considerations
Optimizing template rendering improves application responsiveness:
- Enable template caching - Configure Express with
app.set('view cache', true)in production for faster subsequent renders - Precompile for production - Use
pug.compile()to generate template functions during build rather than runtime - Static generation consideration - For content-heavy pages, pre-render templates at build time using static site generation
- Monitor rendering time - Track template render duration in production to identify performance bottlenecks
// Production view configuration
app.set('view cache', true)
app.set('view options', { cache: true, compileDebug: false })
Development Workflow
Streamlined development processes improve productivity and code quality:
- Hot reload during development - Use tools like nodemon with the
--watchflag to see template changes immediately - Create helper functions - Encapsulate complex data transformations in utility functions imported into templates
- Document patterns - Maintain internal documentation for team members learning your template architecture
- Version control integration - Track template changes alongside corresponding JavaScript changes for complete history
Common Patterns
Modal Dialog Component:
mixin modal(id, title, closable=true)
.modal(id=id, role='dialog', aria-labelledby=`${id}-title`)
if closable
.modal-backdrop(data-dismiss=id)
.modal-content
.modal-header
h3(id=`${id}-title`)= title
if closable
button.close(type='button', data-dismiss=id) ×
.modal-body
block
Form Template with Validation Styling:
mixin form-field(label, name, type='text', required=false, error=null)
.form-group(class={ 'has-error': error })
label(for=name)
= label
if required
span.required *
input(type=type, name=name, id=name, required=required || null, value=value || '')
if error
span.error-message= error
Card Grid Component:
mixin card-grid(items, columns=3)
.card-grid(style=`--columns: ${columns}`)
each item in items
+card(item.title, item.description, item.image)
Following these patterns ensures your Pug templates remain scalable, maintainable, and performant as application complexity grows.
Frequently Asked Questions
Conclusion
Pug provides a powerful, efficient approach to creating dynamic HTML templates for Node.js applications. Its clean syntax reduces boilerplate while maintaining full access to JavaScript's capabilities. By mastering Pug's fundamentals--variables, control flow, template inheritance, and mixins--developers can create maintainable, reusable templates that scale with their applications.
The template inheritance system alone makes Pug valuable for larger applications, enabling consistent layouts without code duplication. Combined with mixins for reusable components and the expressive syntax that eliminates closing tag fatigue, Pug remains a relevant choice for server-side rendering in modern web applications.
Start with simple templates, gradually adopt inheritance and mixins, and establish patterns that work for your team's workflow. The investment in learning Pug pays dividends in code maintainability and development speed.
For organizations building custom web applications, our web development team specializes in modern JavaScript technologies including Node.js, Express, and template engines like Pug. Whether you're starting a new project or migrating existing templates, proper architecture from the beginning ensures scalable, maintainable codebases.
Related Resources:
- JavaScript Either Monad for Error Handling - Advanced JavaScript patterns
- Building REST APIs with Firebase Cloud Functions - Backend development with Node.js
- Using Modern Decorators in TypeScript - Advanced TypeScript features
- Initialize State with React Hooks - React development patterns
Sources
- PugJS Official Documentation - Official API reference and migration guide
- The Valley of Code: The Pug Guide - Comprehensive syntax reference and examples
- GeeksforGeeks: PugJS Basics and Installation - Installation and setup tutorial
- LogRocket: Getting Started With Pug - High-performance template engine guide