Getting Started with Harp

In this post we will take a look at the basics of the Harp static site generator. I hope that this will provide a quick foundation for getting up to speed with this simple yet powerful tool. Additionally I plan on posting more blog posts that dive deeper into Harp while also finding ways to integrate Harp with other tools and in other systems.

Assumptions

  • bash command line
  • npm
  • git

Getting Started

npm install -g harp
mkdir pizza-example
echo "Hello world" > pizza-example/index.ejs
harp server pizza-example
Now open up localhost:9000 and see your hello world HarpJS example in action! Harp is converting the ejs template into an html file. Because we did not specify a specific html file in the url it will look for an index file in the same directory. Because we did not provide a path in our url it looks in the root directory of the project.
git init
git add .
git commit -m "Created a hello world Harpjs example."

Harp Layouts

The first thing we need to do is make a proper layout for our hello world example. To do this create a _layout.ejs file next to index.ejs. Provide the basic html markup in this file:
<!DOCTYPE html>
<html>
  <head>
  </head>

  <body>
  </body>
</html>
Now open up localhost:9000 again. Notice that our hello world is missing? That's because if a _layout file exists in the directory or a parent directory (going up to the root of the project) then it will be used in place of whatever else exists. How do you then provide the contents of the index file into the layout? We do that by using the yield function:
<!DOCTYPE html>
<html>
  <head>
  </head>

  <body>
    <%- yield %>
  </body>
</html>
Now open up localhost:9000. This time you will see your hello world once again.
git add .
git commit -m "Added a layout to the root of the project."

Harp Routing

Now what if we want other pages on our site? All you have to do is create a new file with the .ejs extension. As an example create a file called menu.ejs with the following contents:
<p>Pizza</p>
<p>Pop</p>
<p>Salad</p>
Now open up localhost:9000/menu.html. Harp will look for a file named "menu" in the root of the project directory and will automatically convert menu.ejs into an html file. The contents of the file will be inserted into the layout where the yield was specified.

What if we wanted a page for each of our menu items? Lets take pizza as an example. Go ahead and create a directory within the project root called "menu" and create a file within it called pizza.ejs with the following contents:
<p>This is the pizza page</p>
Now open up localhost:9000/menu/pizza.html and you will see this html again inserted into the layout provided in the root of the project. However what if we wanted to provide a custom layout for the menu item pages? To do this create a _layout.ejs file in the menu folder with the following contents:
<!DOCTYPE html>
<html>
  <head>
  </head>

  <body>
    <p>Custom markup that will go on every menu page, but on no other pages</p>
    <%- yield %>
  </body>
</html>
If you open up the pizza page again you will see that you can now provide the menu pages with a custom layout.
git add .
git commit -m "Added sub pages in the menu directory with a custom layout."

Harp Partials

Now there might be times where a particular piece of a website is reused in multiple layouts or on multiple pages. We can do this by using partials.  Go ahead and create a file in the project root named _header.ejs and provide it with the following contents:
<h1>Welcome to the Pizza example</h1>
Now update the root layout to add the partial function, specifying the partial that we just created:
<!DOCTYPE html>
<html>
  <head>
  </head>

  <body>
    <%- partial("_header") %>
    <%- yield %>
  </body>
</html>
Now it is important to note that the underscore at the beginning of the file name is not necessary however it tells Harp not to render the file as an actual webpage. The same holds true throughout Harp. Files beginning with an underscore are not rendered as apart of the content of the site but are used for other purposes such as layouts, partials, and data, as we will see in the next section. Feel free to reuse this header partial to other files such as the menu/_layout.ejs file.

Notice also that we do not provide the file extension. This is because Harp can handle other templating languages and only cares about the name of the file without the extension. In this blog post we are only covering the ejs templating language.
git add .
git commit -m "Added a header partial for reuse in multiple locations."

Harp Metadata

Now all of our data is currently embedded in the html. What if we want to define this data elsewhere for potential reuse? To do this create a file in the menu directory called _data.json with the following contents:
{
  "pizza": {
    "title": "Pizza",
    "description": "Very tasty and cheesy"
  },
  "pop": {
    "title": "Soda Pop",
    "description": "A sugary beverage"
  }
}
Additionally update the pizza.html file to contain the following:
<h2><%- public.menu._data.pizza.title %></h2>
<p><%- public.menu._data.pizza.description %></p>
Now open up localhost:9000/menu/pizza.html and you will see the json data being pulled into the html. Harp will provide the json within any file named _data.json on the "public" variable which can be access through JavaScript in ejs templates. This means that we have the full power of JavaScript at our disposal.
git add .
git commit -m "Added pizza as metadata instead of embedding it into the html."

Conclusion

Harp is a useful tool for building static websites or can serve as one piece of a larger more dynamic application. In future blog posts I will cover how to use these features of Harp to create a site navigation, breadcrumbs and other contextual features that are often needed in a website. Other possibilities that we may be able to cover is adding dynamic elements to a static website using custom API's or creating a dynamic backend that can generate the JSON data that then can be rendered by Harp.

Comments

Popular Articles

The Vanilla Javascript Component Pattern

The Sunless Citadel: A D&D 5e Session Report