Generating Comments on Static Sites with Staticman

A beginners guide to creating a Jekyll site and using Staticman to allow commenting

In this article I’m going to go through the basics of setting up a Jekyll site, GitHub Pages and Staticman. If you’re just interested in Staticman please skip down a bit!

So I went to a talk recently at LRUG all about pushing Jekyll to breaking point. This talk was given by James Smith (who I am now convinced is some type of Jekyll genius), he did some mad things with Jekyll which as a junior I didn’t understand much of. The main thing I took from his talk was the use of a data directory and have been using it quite a lot to flexibly use data across the tosbourn site. It helped us with our documentation. We had been using a lot of categories and have been able to streamline them. I’ve also started following him on Twitter and noted that he happened to tweet about Staticman so I thought I would give it a look.

Staticman allows you to “bring user-generated content to static sites”. The thing about Jekyll is that it generates static sites, which means that there is no backend code, it spits out HTML pages. This is great because the sites are damn fast and damn secure. This is not great in the way that you can’t have a lot of dynamic content. Here’s where Staticman comes in! It allows a user to use an input form to submit content and Staticman works in the background to take that content and does a Git commit and the content can either be moderated in the form of a pull request or pushed straight to GitHub pages.

So onto what I plan to do with Staticman. Recently my friends asked me to make them a site for their wedding. I initially had planned to make this a Rails project which seemed quite heavy handed for something that will be a few pages of content. I thought I couldn’t use Jekyll as people wouldn’t be able to post to a guestbook but I think Staticman has given me a good work around with this (it’s also nice to play with new tools!).

First I had to create a new project with Jekyll. It is so ridiculously easy to get up and running with it. I’m going to call my project wedding-site.

~ $ gem install jekyll bundler
~ $ jekyll new wedding-site
~ $ cd wedding-site
~/wedding-site $ bundle exec jekyll serve

Once you get your server running, if you go to localhost:4000 in your browser you will see the boilerplate site that Jekyll gives you. The pages which exist here, give guides on how to get up and running. I went through and deleted everything off the site that I wasn’t going to be using.

Next up is getting your site hosted on GitHub Pages, which again is amazingly easy. If you go to the GitHub Pages site it will walk you through everything I am going to do in the rest of this paragraph. Firstly you’ll want to pick a Project site. I didn’t pick a theme as I wanted to start from scratch with my design. If you then go to the GitHub repository for your project and go to the repository settings and navigate down to the GitHub Pages section. Select main branch source and click save. This enables publication to your site via GitHub pages when you push to main, pretty cool eh? If you go to, you will see your fresh new site live on the internet.

Next up I’ve made an index.html file in the root of my directory which will serve as the home page for my site. I’ve included front matter at the top of my file. This serves to let Jekyll know what the layout of the page should be (you can add lots of useful information up here to use later). It looks like this:

layout: default
<h1>My Friends Wedding Site</h1>
<p>Some words about their wedding and love and all that nice stuff.</p>

The front matter is the content between the ---.

So what’s that layout: default stuff about? layout refers to anything which is in the _layout directory, and these are layouts which you can apply to different pages on your site. I have a default.html file in here which I am using but you can have many others. For example on this site ( we have different layouts for different types of articles like posts or reviews. In my default file I have this content:

<!DOCTYPE html>
    <meta charset="utf-8">
    <title>Wedding Site</title>
    {{ content }}
    {% include comments-new.html %}
    {% include comments.html %}

(The code with the curly braces is called Liquid, I’m not going to go into any detail about it in this post.)

Cool. So now this is included on my index.html page. What is content though? Content is simply whatever else you add to the index.html file. My content will be added at the top of the body and above whatever the hell that include stuff is about.

Onto that include stuff. This is a wee bit like the layout/default stuff. In a directory called _includes.The _includes folder is great because you can keep lots of little bits of reusable code that can be references throughout your site (they’re partials). I have two files called comments-new.html and comments.html in this directory. My comments-new file contains this:

<form method="POST" action="">
  <input name="options[redirect]" type="hidden" value="">

  <input name="options[slug]" type="hidden" value="{{ page.slug }}">
  <label><input name="fields[name]" type="text">Name</label>
  <label><input name="fields[email]" type="email">E-mail</label>
  <label><textarea name="fields[message]"></textarea>Message</label>

  <button type="submit">Go!</button>

This is a pretty basic input form but there are a few things to point out because at this stage I’ve started to use Staticman. So I’m going to go through setting that up then we can go back to why some of the things are the way they are on the input form.

You can find out all about Staticman and the documentation on the website. There is a great guide to get you set up which I’m going to go through now (you may find it easier to follow the Staticman site).

Firstly go to your repository and go to the settings page. Navigate to the collaborators and search for staticmanapp and add as a collaborator. Next you need to go to a URL which will be formatted like this If everything went okay you will land on a white page that literally just has the word “OK”.

Next step is to create a file in the root of your directory called staticman.yml. If you are using version 1 of Staticman you will put this information into your _config.yml file but I am using version 2 so I will make this separate file. Which looks like this:

allowedFields: ['name', 'email', 'message']
branch: main
commitMessage: "There's been a new message left!"
filename: "entry{@timestamp}"
format: yml
moderation: false
path: "_data/comments"
requiredFields: ['name', 'email', 'message']

Note the allowedFields here? These are the fields which are in our input form and should be the same.

If we go back to look at the code for our input form now, you will note where the form posts to. They should post to,

So what happens after that? Well you have to choose whether you approve entries in your staticman.yml file. I decided not to, so I set moderation: false. If I had wanted to moderate my comments though I could’ve set moderation: true which would create a pull request for me on GitHub so I could approve the comment first.

Other things to note from my staticman.yml file:

  • branch: main This is the branch which is updated.
  • commitMessage: This is, well, the commit message that goes along with the comment post.
  • filename: "entry{@timestamp}" This will be the name of the file that the comment is saved to.
  • format: yml The format in which the file is saved.
  • path: "_data/comments" This is the where the file will be saved.

Let’s go ahead and make a directory called _data and within that a subdirectory called comments. When someone makes a post to your site this is where you will find the entry for their comment.

Nearly ready to go! A few other things you need before we go. In _config.yml I have something like this:

# site settings
title: My Friends Wedding Site
description: A site for my friends wedding.
baseurl: "" # the subpath of your site, e.g. /blog
twitter_username: ""
github_username:  my-github-name

# Build settings
markdown: kramdown
theme: minima
  - jekyll-feed

If all goes according to plan, when a user goes to your site and makes a comment, when you next do git pull you should have a file in your _data/comments called something like entry1500907955058.yml, which should look like this:

_id: ba52de40-707f-11e7-92fd-1bcb77674161
name: Aunt Gertrude
email: 9ee0f78862120aab8f486fe58472839e
message: What a delightful wedding! I really loved the flowers.
date: 1500907955

Next let’s give Aunt Gertrude her day in the sun with her comment. If make a comments.html within our _includes folder and pop this inside:

{% assign comments = | sort %}

{% for comment in comments reversed %}
  {% assign commentData = comment[1] %}
      {{ commentData.message }}<br>
      From: {{ }}<br>
      {{ | date_to_long_string }}
{% endfor %}

This code will loop through each file in _data/comments and spit out the message, name and date.

Looking back through the input form code:

<input name="options[redirect]" type="hidden" value="">

You’ll note that we have a redirect, this will help to hide the fact that the input isn’t loaded dynamically and I just redirect to a “Thanks” page. In Jekyll if we just make a directory called thanks which contains an index.html page with our thanks message.

So the user will fill in the form, get redirected to the “Thanks” page and if they were to visit the home page again they will see their comment.

This should be enough to get you started with a super basic Jekyll site with user comment input with Staticman. I have put all the code I used here in a repository which you can have a look at. Hopefully you’ve found this post useful albeit a little long!

Recent posts View all


The best way to test model scopes in Rails

Learn about Rails scopes and how to best test them with both Rspec and Minitest


Finding out what called a Ruby method

A quick way to understand what is calling your code using the caller method