Static Site E-Commerce: Integrating Snipcart with Middleman

Among developers, static websites are gaining a lot of traction these days (and they deserve it). They're simple, fast and scalable. Much like Snipcart, as a matter of fact. Thing is, static website development is quick and cheap, and so is the hosting. For years, dynamic websites had the upper hand when it came to the "functionality" argument. Today, there's an ever growing number of 3rd party solutions and applications that you can easily integrate with static websites. Developers can pretty much do everything they want with them, as long as they're using the right tools. In this post, we'll be focusing on handling the e-commerce aspect of a static website. More precisely, I'll show you how to add our JavaScript/HTML-based shopping cart to your static site using Middleman.

Just so you know, we created a GitHub repository containing all the code for this post. You can find it here.

Middleman, you say?

snipcart-middleman-static-site-logo

Middleman is a static site generator using all the shortcuts and tools in modern web development.

We first heard about Middleman when we sat down with Dillon Morton, a Colorado web developer. He had used the app to handle his static e-commerce website for his clothing brand, and seemed pretty happy about it. We've been eager to try it out for ourselves for a while now, so let's bite into the thick of it.

Integrating Snipcart with Middleman: getting started

Quick disclaimer: for this post, I'm assuming you have Ruby installed, RubyGems working and a basic knowledge of Middleman. You can learn how to install Ruby on your Mac here and on your Windows here. There's also a ton of useful information regarding RubyGems here. And if you don't know much about Middleman, I strongly suggest you go through their documentation to get familiar with its awesome features.

First, install Middleman.

gem install middleman

In your project folder, you will need to init a new Middleman application using their CLI.

middleman init

Middleman will create the basic project structure. You will have a source folder created and some other files. The source folder will contain your templates, stylesheets, and any other assets.

To start a development server you can just do:

middleman server

Your website will then run on a local server on your dev machine. Just hit the local URL that you will see in your terminal.

Adding Snipcart products to Middleman

For this demo, I decided to use a simple yml file as our datastore. Middleman works great with this, and it will be easy to deploy / update.

At the root of your project, create a data folder. I named mine products.yml.

I added three products with some properties required by Snipcart.

- name: Small bag
  id: 1001
  price: 169.99
  max_quantity: 10
  path: products/small-bag
  image: http://placehold.it/350x200

- name: Leather bag
  id: 1002
  price: 200.00
  max_quantity: 20
  path: products/leather-bag
  image: http://placehold.it/350x200
  
- name: Messenger bag
  id: 1003
  price: 99.99
  max_quantity: 5
  path: products/messenger-bag
  image: http://placehold.it/350x200

This data will be available in your templates using data.products.

Setting up the layout page

I personally like to use Foundation when doing demos or prototyping something quick. This post isn't about showing all the power of Middleman; it's about deploying a static website using Snipcart, as fast as possible. So I will go straight forward and reference Foundation using cdnjs CDN server.

I know that some Middleman templates exist with Foundation pre-configured, so feel free to submit pull requests to the demo repository if you want. :)

In my layout.erb file I will add the following lines to include Foundation and jQuery:

<!-- Include jQuery -->
<%= javascript_include_tag "//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js" %>

<!-- Include Foundation -->
<%= stylesheet_link_tag "//cdn.jsdelivr.net/foundation/5.5.0/css/foundation.min.css" %>
<%= javascript_include_tag "//cdn.jsdelivr.net/foundation/5.5.0/js/foundation.min.js" %>

I've also deleted the default Middleman stylesheet named all.css in the source/stylesheets folder.

Then, I will add a simple nav bar, just to make the site look a little better.

Now add these lines to the body tag just before <%= yield %>:

<nav class="top-bar" data-topbar role="navigation">
  <ul class="title-area">
    <li class="name">
      <h1>
        <a href="#">Snipcart</a>
      </h1>
    </li>
  </ul>
</nav>

Of course, I will also include Snipcart's required files! Log into your Snipcart dashboard, go to Account > Credentials and paste the code you need to add. We will add it in the layout just before Foundation.

We could just copy / paste it, but I want to be consistent, so I will use Middleman helpers.

<!-- Include Snipcart -->
<%= javascript_include_tag  "https://app.snipcart.com/scripts/snipcart.js",
    :id => "snipcart",
    :"data-api-key" => ENV["snipcart-api-key"] %>
<%= stylesheet_link_tag "https://app.snipcart.com/themes/base/snipcart.css" %>

You will need to define an environment variable somewhere with your Snipcart Test or Live API Key. As I will use Netlify for deployment, I will add my variable in their dashboard, but you could simply add it into your config.rb file.

ENV["snipcart-api-key"] = "YOUR_API_KEY"

Setting up the index

On the main page, I want to display all my products. Here, I've completely removed the content of the index.html.erb file created by Middleman.

I started by adding the page title using yml markup.

---
title: My awesome store
---

Then, I will add an h1 tag.

<div class="row">
  <h1>
    Products
  </h1>
</div>

I now want to display all my products by getting them from the products.yml file I've created, and Middleman makes it very easy.

You can loop through your products using the data object.

<% data.products.each do |p| %>
    <%= p.name %>
<% end %>

I will use the Foundation block grid component to show my products.

<div class="row">
  <ul class="small-block-grid-1 large-block-grid-3">

    <% data.products.each do |b| %>
      <li>
        <a href="<%= b.path %>">
          <%= image_tag b.image %>
        </a>

        <div>
          <strong><%= b.name %></strong>
        </div>

        <div>
          <%= number_to_currency(b.price, :unit => "$") %>
        </div>

      </li>
    <% end %>

  </ul>
</div>

Okay, it is time to take a look at what I have done up until now. Open the website in a browser and you will see a list of products, like this.

Home page

Creating a product page

First step is to create a new erb template. I will call it product.html.erb. Create this file at the root of the source folder.

This template will be used to display the product information and the Snipcart buy button.

I decided to create a simple two columns template with the product image, Snipcart button, product name and its description.

---
title: product.name
---

<div class="row">
  <div class="large-6 small-12 columns text-center">
    <%= image_tag product.image %>

    <%= snipcart_button product, "Add to cart" %>
  </div>

  <div class="large-6 small-12 columns">
    <h1>
      <%= product.name %>
    </h1>

    <p>
      <%= product.description %>
    </p>
  </div>
</div>

Did you notice the snipcart_button product line? Unfortunately, it will not magically work; we have a little extra step to do. We will create a template helper to generate a Snipcart button.

Open your config.rb file and add those lines:

helpers do
  def snipcart_button (p, text)
    args = {
      :"class" => "snipcart-add-item",
      :"data-item-id" => p.id,
      :"data-item-price" => p.price,
      :"data-item-name" => p.name,
      :"data-item-url" => current_page.url,
      :"data-item-max-quantity" => p.max_quantity
    }

    content_tag :button, args do
      text
    end
  end
end

Now, when we call snipcart_button inside a template, our add to cart button will be displayed with product information.

Okay, now that we have a template and a helper to generate the Snipcart button, we need to be able to display it when the product URL is called. To do so, we have to use what Middleman calls a proxy. To know more about this, I suggest you to read this part of the documentation on their website.

In my config.rb file, I added these lines:

data.products.each do |p|
  proxy p.path, "products.html", :locals => { :product => p }, :ignore => true
end

When we defined our products in the products.yml file, we specified a path. This path will be used as the unique URL to access the resource.

Now, open your browser (make sure your Midldeman server is started) and hit a product page such as http://localhost:4567/products/small-bag. You should now see the product and be able to add it to your cart!

Site without Snipcart Site with Snipcart

Deploying your static e-commerce site using Netlify

Netlify's an awesome product developed by the same (good) guys who created BitBalloon. In a nutshell, it allows developers to focus on the code while Netlify builds, deploys and hosts their static sites. That's what we'll be using to deploy our Middleman site.

First, I will install Netlify command line tools.

npm install netlify-cli -g

Then in the root of my project, I will init a new Netlify site. We can't use the simple netlify deploy command because we are using a static site generator. We will use what Netlify calls Continuous Deployment. Run the following command in any terminal.

netlify init

You will then have a few questions to answer.

 Directory to deploy (blank for current dir):  build
 Your build command (middleman build/grunt build/etc):  middleman build

You will then be asked to enter your GitHub credentials in order to create a SSH Key on your behalf. Once it is done, you should't have to enter your credentials again.

Once it is completed, the website will be created with a random name. I will then update my site name because I want snipcart-middleman.netlify.com.

netlify update -n snipcart-middleman

After about a minute, my site is deployed! Well, that was easy!

One last thing: I need to add my Snipcart API key in an environment variable. Actually, we can't add an environment variable with Netlify CLI (or I simply did not find how to do it in the documentation), but it would be great to be able to! :) So I open Netlify Web UI:

netlify open snipcart-middleman

Then I will add a new environment variable called snipcart-api-key.

Once it is done, I will redeploy my current site.

netlify deploy

That's it; my site is now built, deployed and blazing fast!

##So, here's to static web development

Thanks to applications and services like Middleman and Netlify, creating, managing and deploying static websites is more efficient than ever. Because those lean, static tools are focused on code and simplicity, it makes them a perfect fit for an HTML/JS-based shopping cart like Snipcart. Past integrations with services like CloudCannon and BitBalloon, for instance, also worked like a real charm. We've picked Middleman for this how-to post because we had heard plenty positive feedback, but we could've used any static site generator. We could've also gone with Jekylll, another developer favourite. Needless to say, we're pretty thrilled about the traction the whole static movement is getting. We hope this post gave you a good idea of how well you can handle e-commerce on static sites.


Have you used any of the tools we mentioned in the post yet? If so, we'd love to hear your experiences and thoughts in the comments. And of course, if you found the article interesting and useful, feel free to share it wherever you see fit!

Suggested posts: