Starting up with Harp

Oct 12, 2013

The obvious place to check when starting up with another new tool is its documentation page. Harp has a pretty good set of documentation, but in many ways it could be improved. What I normally enjoy when starting up with frameworks of some sort is to have a real-case tutorial example explained.

Install & Run

As describe in the quick-start guide, starting with harps is as simple as executing the following :

sudo npm install harp -g
mkdir hello-world
cd hello-world
echo "h2 Hello World" > index.jade
harp server

You are now ready to access your harp application by opening http://localhost:9000. Now Harp will "listen" to any changes you make to your project folder (modify existing files, creating new ones etc...) and dynamicly compile all this to html and css.

Deploy or Freeze!

Harp requires nodejs to be installed, and nowadays it's not very common to find cheap or free solutions for hosting nodejs applications. Your concern might even be that you just prefer to serve stupid static files with solutions optimized for that (Nginx, G-WAN, etc...). Anyway, Harp allows you to compile your project to pure html and saves all the generated files in a www/ folder at the root of your project ready to be uploaded to your server.

harp compile

Layout & Partials

Layout

Most of the time you will want to create a layout which would be applied to all the page you create. In Harp you can do this by creating at the root of you project a _layout.jade (again it could be _layout.ejs if you prefer) file in which the only requirement is to have a yield property output

echo "h1 Layout header

!= yield" > _layout.jade

See how index.jade now inherits from _layout.jade. Obivously this layout file will be far more "complex", but the idea is precisely to delegate all the layout complexity to this 1 file, and keep the other plain simple.

Partials

Partials are files which can be included in other files by simply calling the partial() method. You typically use partial for being able to be able to reuse chunks of html in different places, or simply to keep you layout or calling file clean and organised. I use partial for storing disqus's html/js code and google analytics's tag. Best practice from Harp says that those files should (can) be stored in a _shared/ directory. Directory names starting with _ will be ignored by Harp (also when using calling harp compile).

mkdir _shared
echo "small copyright note..." > _shared/copyright.jade
echo "!= partial(\"_shared/copyright\")" >> _layout.jade

You can passe objects (variables) to your partials partial("_shared/copyright", { "year": 2013 })

Variables (globals, current, metadata)

Because all this is built on top of nodejs, we have the possibility to define and/or access different types of variables.

Globals

Global variables can be accessed... globally through out your project. Use it to define you site title, your base url etc... They are defined in json format in a reserved file harp.json stored at the root of your project :

# /harp.json
{
    "globals": {
        "title": "Acme Site",
        "name": "John Doe",
        "uri": "http://example.com"
    }
}

What I discovered when staring to work with globals, is that Harp expects all the files to be stored in a public/ directory if a harp.json exists, otherwise keep your files at the root of your project.

  • Without harp.json file
    $ tree
    .
    ├── index.jade
    └── _layout.jade
  • With harp.json file
    $ tree
    .
    ├── harp.json
    └── public
        ├── index.jade
        └── _layout.jade
        

Now you have access anywhere in your files being servered by Harp to the variable title for instance :

# accessible through http://localhost:9000/variable
echo "h2 Starting up with Harp" > public/variable.jade

Current

Harp also provides a current object holding the current path and source. See the official documentation, it is very well explained. This is useful when constructing navigation toolbar for example, where you usually want the current page to be highlighted in the menu.

Metadata

Apart from the special harp.json file living the your root directory, Harp also allows you to stored "metadata" variable which should be stored in _data.json files in the directory where you will want to access those metadata. The typical example exposed in their example is a list of "slugs" for different articles published, together with a publishing date and article name. These objects are then used to create a "semi-dynamic" list of article titles with a link to each of them.

I'm personally using it for listing my blog posts. And I'm thinking of extending its use to create a page of 2nd hand items I would like to sell. It could also be a nice way to create an image gallery maybe.

Stylesheets

Not only does Harp compile .jade, .ejs or .md files, it also compiles .less and .stylus files making it a breeze to update your stylesheets. Let's improve our layout file, use bootstrap for styling it, and try to customize a wee bit the default design obtained.

Bower

While this is completely unrelated to this post, I try to use bower for keeping my assets versions nice and clean.

echo "{}" > package.json
npm install bower --save
echo "{\"directory\": \"vendor\"}" > .bowerrc
echo "{\"name\": \"test\"}" > bower.json
bower install bootstrap --save

Customize stylesheet with LESS

So that we have bootstrap source code in a ~/vendor/ directory, we can go ahead and update our layout file (this is a strict translation of Bootstrap starter template to jade only with the extra != yield call for harp to show our added content :

# ~/public/_layout.jade
!!!
html
    head
        meta(charset="utf-8")
        meta(name="viewport", content="width=device-width, initial-scale=1.0")
        meta(name="description", content="")
        meta(name="author", content="")
        title Starter Template for Bootstrap
        link(rel="stylesheet", type="text/css", href="/css/main.css")
    body
        div(class="navbar navbar-inverse navbar-fixed-top")
            div.container
                div.navbar-header
                    button(class="navbar-toggle", type="button", data-toggle="collapse", data-target=".navbar-collapse")
                        span.icon-bar
                        span.icon-bar
                        span.icon-bar
                    a.navbar-brand(href="/") Project name
                div(class="collapse navbar-collapse")
                    ul(class="nav navbar-nav")
                        li(class="active")
                            a(href="#") Home
                        li
                            a(href="#about") About
                        li
                            a(href="#contact") Contact
        div.container
            div.starter-template
                h1 Bootstrap starter template
                p.lead
                    | Use this document as a way to quickly start any new project.
| All you get is this text and a mostly barebones HTML document. != yield

And now we can create our main stylesheet file ~/public/css/main.less and start overriding bootstrap @body-bg value :

mkdir public/css
echo "@import \"../../vendor/bootstrap/less/bootstrap.less\";
    @body-bg: yellow;
    body {
      padding-top: 50px;
    }
    .starter-template {
      padding: 40px 15px;
      text-align: center;
    }" > public/css/main.less
    

Harp takes care of compiling your less file(s) and dump all of its content in the /css/main.css referenced in our layout!

We are now ready to compile our project so it is ready to deploy on a static web server.

$ harp compile
$ tree www/
www/
├── css
│   └── main.css
├── index.html
└── variable.html

Wrap up

I've only started playing with Harp and this is a small guide on how I got started. I would be happy to hear about other people's experience with it, but so far I'm liking it a lot. It is simple and light and I think I may have found my solution for being able to post a bit more.

What's next? I'll explain how I used Harp as a "pseudo" blog engine. One thing I still haven't had time to tackle yet is RSS feed and sitemap generation. Maybe there is a good opportunity here for the creators of Harp (or its community if they manage to create one) to create a repository of partials/mixins for solving these common issues.

comments powered by Disqus