Learn how to integrate Pug with Express.js to create dynamic, server-side rendered HTML pages. This tutorial guides you through setting up Pug, creating templates, and passing data from Express to Pug for efficient content rendering.



What is Pug?

Pug (formerly Jade) is a high-performance templating language for Node.js. It uses simplified, indentation-based syntax to generate HTML, making it concise and readable. When used with Express.js, Pug can render HTML on the server, allowing for flexible and customizable content based on data passed from the backend.

Install Express.js and Pug

To get started, ensure Node.js is installed. Then, create a new Express project and add the necessary dependencies:

npm init -y
npm install express pug

Configure Pug as the View Engine in Express

In your main server file (usually app.js or server.js), configure Express to use Pug as its templating engine:

const express = require('express');
const app = express();

// Set Pug as the templating engine
app.set('view engine', 'pug');

// Optional: Specify a custom directory for Pug views
app.set('views', __dirname + '/views');

Pug Project Structure

Here's an example of a complete Express project structure, including directories for Pug templates, reusable partials, and static assets:

express-pug-app/
├── views/
│   ├── partials/
│   │   ├── header.pug
│   │   └── footer.pug
│   └── pages/
│       ├── home.pug
│       ├── items.pug
│       └── products.pug
├── public/
│   ├── css/
│   ├── js/
│   └── images/
└── app.js

Create a Pug Template File

Inside the views/pages directory, create a .pug file to serve as your HTML template. Pug files use indentation rather than HTML tags, making them simpler to write and read.

//- views/pages/home.pug
doctype html
html(lang="en")
  head
    meta(charset="UTF-8")
    meta(name="viewport", content="width=device-width, initial-scale=1.0")
    title= title
  body
    h1= message
    p This is a dynamic page rendered with Pug and Express.js.

In this example, title and message are dynamic values that will be passed from the server to the template.

Understanding Pug Syntax

Pug uses a minimal syntax, making it easy to write dynamic HTML. Here are a few essential rules:

  • Plain Text: Lines without tags or variables are rendered as plain text.
    p This is a paragraph in Pug.
  • Dynamic Variables: Use = after a tag to insert dynamic content passed from Express.
    h1= title  // Outputs the title variable
    
  • HTML Attributes: Define attributes within parentheses after a tag. Multiple attributes are separated by spaces.
    a(href="/contact" class="nav-link") Contact Us
    
  • Interpolation: Use #{} within text to embed variables or expressions.
    p Welcome, #{user.name}!
    
  • Conditionals: Use if, else if, and else for conditional rendering.
    if user
      p Welcome, #{user.name}!
    else
      p Please log in to continue.
    
  • Loops: Use each to loop through arrays and render a list or series of elements.
    ul
      each item in items
        li= item
    

Note: Proper indentation is crucial in Pug, as it defines the structure of your HTML. Consistent indentation ensures that nested elements are rendered correctly.

Passing Data from Express to Pug

Use res.render() in Express to send data to your Pug template. The data is passed as an object and can be accessed in Pug using the variable names directly:

// Define a route
app.get('/', (req, res) => {
  res.render('pages/home', { title: 'Welcome', message: 'Dynamic content with Pug and Express!' });
});

Using JavaScript Logic in Pug

Pug allows you to embed JavaScript logic, such as loops and conditionals, directly in your templates. This makes it simple to display lists, handle conditions, and create dynamic content.

// Route to render a list of items (example route)
app.get('/items', (req, res) => {
  const items = ['Laptop', 'Smartphone', 'Tablet'];
  res.render('pages/items', { items });
});

In the items.pug file:

//- views/pages/items.pug
doctype html
html(lang="en")
  head
    meta(charset="UTF-8")
    meta(name="viewport", content="width=device-width, initial-scale=1.0")
    title Items List
  body
    h1 Items:
    ul
      each item in items
        li= item

Including Partials

Pug makes it easy to reuse code by allowing you to include "partials" — separate template files for reusable components like headers, footers, or navigation bars. This helps keep your code clean and manageable, especially for larger applications.

Creating Partials

To make the header and footer reusable, create two separate .pug files in a partials directory under views.

Header Partial (header.pug):

//- views/partials/header.pug
header
  nav
    a(href="/") Home
    a(href="/about") About Us

Footer Partial (footer.pug):

//- views/partials/footer.pug
footer
  p © 2024 Your Company

Using Partials in Main Templates

To include a partial in a main Pug template, use the include keyword:

//- views/pages/home.pug
doctype html
html(lang="en")
  head
    meta(charset="UTF-8")
    meta(name="viewport", content="width=device-width, initial-scale=1.0")
    title= title
  body
    include ../partials/header

    h1 Main Content
    p Welcome to our dynamic page rendered with Pug and Express.js.

    include ../partials/footer

With this setup, the header.pug and footer.pug partials are loaded automatically into any page that includes them, keeping your templates organized and your code more maintainable.

Complete Example

Let's bring everything together with a full example that includes routes, templates, and partials to create a simple product catalog. This example demonstrates how to structure your code, use partials, and pass data from Express to Pug.

Setting Up app.js

Start by creating an Express server in app.js. Here, we'll set up Pug as the templating engine, define sample data, and create a route to display a list of products.

const express = require('express');
const app = express();

// Set up Pug as the templating engine
app.set('view engine', 'pug');

// Route to render the home page
app.get('/', (req, res) => {
  res.render('pages/home', { title: 'Welcome', message: 'Dynamic content with Pug and Express!' });
});

// Route to render a list of items (example route)
app.get('/items', (req, res) => {
  const items = ['Laptop', 'Smartphone', 'Tablet'];
  res.render('pages/items', { items });
});

// Sample product data for product catalog
const products = [
    { id: 1, name: 'Laptop', price: 75000 },
    { id: 2, name: 'Smartphone', price: 50000 },
    { id: 3, name: 'Tablet', price: 35000 }
];

// Route to render the products page
app.get('/products', (req, res) => {
    res.render('pages/products', {
        title: 'Product Catalog',
        products: products
    });
});

// Start the server on port 3000
app.listen(3000, () => {
    console.log('Server running on http://localhost:3000');
});

Creating the products.pug Template

In the views/pages directory, create a products.pug file to display the product catalog. Use partials for the header and footer to keep the template organized.

//- views/pages/products.pug
doctype html
html(lang="en")
  head
    meta(charset="UTF-8")
    meta(name="viewport", content="width=device-width, initial-scale=1.0")
    title= title
  body
    include ../partials/header

    main
      h1= title
      .products
        each product in products
          .product
            h2= product.name
            p Price: ₹#{product.price}

    include ../partials/footer

Conclusion

In this tutorial, you've learned how to set up and configure Pug as a templating engine in Express.js, create and render dynamic HTML pages, pass data from Express to Pug, and use JavaScript logic in Pug templates to handle loops, conditionals, and partials. With this knowledge, you can now build data-driven, server-side rendered applications with flexible and customizable content.



Found This Page Useful? Share It!
Get the Latest Tutorials and Updates
Join us on Telegram