SitePoint
  • Premium
  • Library
  • Community
  • Jobs
  • Blog
LoginStart Free Trial
A Beginner’s Guide to Pug
A Beginner’s Guide to Pug
Notice of Rights
Notice of Liability
Trademark Notice
About the Author
About SitePoint
What’s a Template Engine and Why Do I Need One?
A Little History
Installing Pug
Pug’s Basic Syntax
Conclusion

A Beginner’s Guide to Pug

As web designers or developers, we likely all have to write our fair share of HTML. And while this is not the most difficult task, it can often feel a little boring or repetitive. HTML is also static, which means that if you want to display dynamic data (fetched from an API, for example), you invariably end up with a mishmash of HTML stings inside JavaScript. This can be a nightmare to debug and to maintain.

This is where Pug comes in. Pug is a template engine for Node and for the browser. It compiles to HTML and has a simplified syntax, which can make you more productive and your code more readable. Pug makes it easy both to write reusable HTML, as well as to render data pulled from a database or API.

In this guide, I’ll demonstrate how to get up and running with Pug. We’ll start by installing it from npm, go over its basic syntax and then look at several examples of using JavaScript in Pug. Finally, we’ll explore a couple of Pug’s more advanced features by building a simple Node/Express project which uses Pug as its template engine.

What’s a Template Engine and Why Do I Need One?

Before we start looking at Pug, let’s take a second to understand the concepts involved.

A template engine is a program which is responsible for compiling a template (that can be written using any one of a number of languages) into HTML. The template engine will normally receive data from an external source, which it will inject into the template it’s compiling. This is illustrated by the following diagram.

Credit: Dreftymac, TempEngWeb016, CC BY-SA 3.0

This approach allows you to reuse static web page elements, while defining dynamic elements based on your data. It also facilitates a separation of concerns, keeping your application logic isolated from your display logic.

You’re more likely to benefit from a template engine if your site or web application is data driven — such as a staff directory for administering employees, a web store that lists various products for users to buy, or a site with dynamic search functionality.

You won’t need a template engine if you’re fetching a small amount of data from an API (in which case you can just use JavaScript’s native template strings), or if you’re making a small static site.

A Little History

It’s also worth noting that Pug used to be called Jade until it was forced to change its name due to a trademark claim in 2015. The name change took effect with version 2.0.

There’s still a lot of Jade-related material available online. And while some of it’s probably still quite valid, the fact that the name change coincided with a major version bump means that Pug’s syntax has several differences, deprecations, and removals compared to its predecessor. These are documented here.

If you’re interested in finding out more, you can read the original name change announcement in this GitHub issue. Otherwise, just be sure to add the word “template” to your Pug-related Google searches to avoid the results being full of pooches.

Installing Pug

Before we can get to writing some Pug, we’ll need to install Node, npm (which comes bundled with Node) and the pug-cli package.

There’s a couple options for installing Node/npm. Either head on over to the project’s home page and download the correct binaries for your system, or use a version manager such as nvm. I would recommend using a version manager where possible, as this will allow you to install different Node versions and switch between them at will. It will also negate a bunch of potential permissions errors.

You can check out our tutorial “ Installing Multiple Versions of Node.js Using nvm ” for a more in-depth guide.

Once Node and npm are installed on your system, you can install the pug-cli package like so:

Code snippet

npm i -g pug-cli

You can check that the install process ran correctly by typing pug --version into a terminal. This will output the version of Pug and the version of the CLI that you have installed.

At the time of writing, this was as follows:

Code snippet

$ pug --versionpug version: 2.0.3pug-cli version: 1.0.0-alpha6

Syntax Highlighting in Your Editor

If your editor doesn’t offer syntax highlighting for Pug, it’d be a good idea to look for an extension to add this functionality.

I’m currently using Sublime Text 3 and, out of the box, this is what a .pug file looks like:

Pug without syntax highlighting

To remedy this, one can install the Sublime Pug package:

Pug with syntax highlighting

Syntax highlighting will make it much easier to work with Pug files, especially those of any length.

Try Pug without Installing

If you’d like to follow along with the simpler examples in this tutorial, you can also run them in various online code playgrounds.

CodePen, for example, has Pug support baked right in. Simply create a new pen, then select Settings > HTML and choose Pug as your preprocessor. This will allow you to enter Pug code into the HTML pane and see the result appear in real time.

As an added bonus, you can click on the down arrow in the HTML pane and select View Compiled HTML to see the markup that Pug has generated.

Pug’s Basic Syntax

Now that we’ve got Pug installed, let’s try it out. Create a new directory named pug-examples and change into it. Then create a further directory called html and a file called index.pug:

Code snippet

mkdir -p pug-examples/htmlcd pug-examplestouch index.pug

Note for Windows Users

The touch command is Linux/macOS specific. Windows users would do echo.> index.pug to achieve the same thing.

The way this is going to work is that we’ll write our Pug code in index.pug and have the pug-cli watch this file for changes. When it detects any, it will take the contents of index.pug and render it as HTML in the html directory.

To kick this off, open a terminal in the pug-examples directory and enter this:

Code snippet

pug -w . -o ./html -P

You should see something like the following:

Code snippet

watching index.pugrendered /home/jim/Desktop/pug-examples/html/index.html

Understading the Code Above

In the above command, the -w option stands for watch, the dot tells Pug to watch everything in the current directory, -o ./html tells Pug to output its HTML in the html directory and the -P option prettifies the output.

Now let’s create the page from the screenshot above (the one complaining about the lack of syntax highlighting). Enter the following into index.pug:

Code snippet

doctype htmlhtml(lang='en') head   title Hello, World! body   h1 Hello, World!   div.remark     p Pug rocks!

Save pug.index and then inspect the contents of ./html/index.html. You should see the following:

Code snippet

<!DOCTYPE html><html lang="en">  <head>    <title>Hello, World!</title>  </head>  <body>    <h1>Hello, World!</h1>    <div class="remark">      <p>Pug rocks!!</p>    </div>  </body></html>

Not bad, eh? The Pug CLI has taken our Pug file and rendered it as regular HTML.

This example serves to highlight a couple of important points about Pug. Firstly, it is whitespace sensitive, which means that Pug uses indentation to work out which tags are nested inside each other. For example:

Code snippet

div.remark  p Pug rocks!!

The code above produces this:

Code snippet

<div class="remark">  <p>Pug rocks!!</p></div>

Now take this code:

Code snippet

div.remarkp Pug rocks!!

This produces the following:

Code snippet

<div class="remark"></div><p>Pug rocks!!</p>

It doesn’t really matter what level of indentation you use (you can even use tabs if you have to), but it’s highly recommended that you keep the level of indentation consistent. In this article I’ll be using two spaces.

Secondly, Pug doesn’t have any closing tags. This will obviously save you a fair few keystrokes and affords Pug a clean and easy-to-read syntax.

Now that we’ve got a handle on some basic Pug, let’s quickly go over its syntax. If any of this seems confusing, or you’d like to go more in-depth, be sure to consult the project’s excellent documentation.

DOCTYPE

You can use Pug to generate a number of document type declarations.

For example doctype html will compile to <!DOCTYPE html>, the standard HTML5 doctype, whereas doctype strict will give us <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">. Pug will do its best to ensure that its output is valid for the document type.

Tags

As mentioned, Pug doesn’t have any closing tags and relies on indentation for nesting. This might take a small amount of getting used to, but once you do, it makes for clean and readable code. By way of an example:

Code snippet

nav  navbar-default  div    h1 My Website!  ul    li      a Home    li      a Page 1    li      a Page 2  input

The code above compiles to this:

Code snippet

<nav>  <div>    <h1>My Website!</h1>  </div>  <ul>    <li><a>Home</a></li>    <li><a>Page 1</a></li>    <li><a>Page 2</a></li>  </ul>  <input/></nav>

Notice that Pug is smart enough to close any self-closing tags (such as the <input /> element) for us.

Classes, IDs and Attributes

Classes and IDs are expressed using a .className and #IDname notation. For example:

Code snippet

nav#navbar-default  div.container-fluid    h1.navbar-header My Website!

Pug also offers us a handy shortcut. If no tag is specified, it will assume a <div> element:

Code snippet

nav#navbar-default  .container-fluid    h1.navbar-header My Website!

Both of these compile to:

Code snippet

<nav id="navbar-default">  <div class="container-fluid">    <h1 class="navbar-header">My Website!</h1>  </div></nav>

Attributes are added using brackets:

Code snippet

ul    li      a(href='/') Home    li      a(href='/page-1') Page 1    li      a(href='/page-2') Page 2
  input.search(    type='text'    name='search'    placeholder='Enter a search term...'  )

This results in the following:

Code snippet

<ul>  <li><a href="/">Home</a></li>  <li><a href="/page-1">Page 1</a></li>  <li><a href="/page-2">Page 2</a></li></ul><input class="search" type="text" name="search" placeholder="Enter a search term..."/>

There’s a lot more to say about attributes. For example, you could use JavaScript to include variables in your attributes, or assign an array of values to an attribute. We’ll get on to using JavaScript in Pug in the next section.

Plain Text and Text Blocks

Pug provides various methods for adding plain text directly into the rendered HTML.

We’ve already seen how to add plain text inline:

Code snippet

h1.navbar-header My Website! We can write anything we want here …

Another way is to prefix a line with a pipe character (|):

Code snippet

p  | You are logged in as  | user@example.com

This gives us the following:

Code snippet

<p>  You are logged in as  user@example.com</p>

When dealing with large blocks of text, you can just ad a dot . right after the tag name, or after the closing parenthesis, if the tag has attributes:

Code snippet

p.  Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod  tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim  veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea  commodo consequat.

This results in:

Code snippet

<p>  Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod  tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim  veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea  commodo consequat.</p>

Comments

Finally, comments can be added like so:

Code snippet

// My wonderful navbarnav#navbar-default

This comment will be added to the rendered HTML:

Code snippet

<!-- My wonderful navbar--><nav id="navbar-default"></nav>

You start a comment like so:

Code snippet

//- My wonderful navbarnav#navbar-default

When you do this, the comment will remain in the Pug file but won’t appear in the HTML.

Comments must appear on their own line. Here, the comment will be treated as plain text:

Code snippet

nav#navbar-default // My wonderful navbar

Multiline comments are possible, too:

Code snippet

//  My wonderful navbar  It is just so, awesome!nav#navbar-default

Basic Syntax Demo

Below you can find a demo of a Bootstrap-style layout which demonstrates the techniques we’ve discussed so far:

Live Code

End of PreviewSign Up to unlock the rest of this title.

Community Questions