Pjax & Middleman (or any other static site generator)

How to use pjax for your static sites
Published on Aug 4, 2014

You probably know pjax. But what if you want to use it with static pages for example generated by Middleman? If you don't know pjax, here's a short quotation from official pjax site:

Pjax loads html from your server into the current page without a full page load. It's ajax with real permalinks, page titles, and a working back button that fully degrades.

Pjax

If you don't know how to use pjax. Download jquery.pjax.js into your source/javascripts directory

curl -sSL
https://raw.githubusercontent.com/defunkt/jquery-pjax/master/jquery.pjax.js -o
source/javascripts/jquery.pjax.js

In your default layout source/layouts/application.html.erb add container around yield to look similar to:

<div id="container"><%= yield %></div>

Now enable pjax and let it know to use your container for rendering pages. Edit source/javascripts/all.js and add

$(document).pjax('a', '#container');

Using it with static sites

In dynamic application like for example Rails app, it's easy. You'll just add condition to check for HTTP_X_PJAX header and if it's present, you'll render different layout, but with static sites it's little bit different.

Here's a quick tip. First of all create a custom minimalistic pjax layout. For example create source/layouts/pjax.html.erb. For starters we'll display only page title and view content.

<title><%= current_page.data.title || "My Awesome Dynamic Site" %></title>

<%= yield %>

And let the middleman know, that you want to generate also pages with alternative pjax layout. In config.rb just choose which pages you want to have pjax on. I'm using proxy method for that and I'm generating alternative layout into the pjax/ subdirectory:

[:index, :about].each do |page|
  proxy "/pjax/#{page}.html", "/#{page}.html", layout: "pjax"
end

Configuring Nginx

Now when everything is prepared, it's time to emulate that dynamic part. Configure your web server to send pjax/ pages when the HTTP_X_PJAX header is present. Personally I love Nginx, so I've added this snippet to my nginx.conf into the server block of my middleman site. Sample would look like this:

server {
  server_name foo.bar;
  root /var/www/foo;
  location / {
    if ($http_x_pjax = true) {
      root /var/www/foo/pjax; # Pjax request, use different root
      break;
    }
  }
  # etc...
}

Test it

Now everything should be working, middleman build and deploy it to your Nginx server. Page changes should be rendered throughout pjax now.