Software in context

Tags


How to Use GitHub as a Minimal CMS

22nd January 2016

For a few months I've been thinking about a minimal content management system—a CMS—for this blog. A CMS is useful because it separates the parts of a website that tend to change often from those that don't. For example, the code for this website is checked into a git repository on Bitbucket, but all the content is managed through the Ghost blog platform. It's convenient to create and edit posts in a system designed for writing. It wouldn't be convenient to have to commit, push, build and deploy this website every time I fixed a typo.

Above, a recent hike up San Jacinto Peak

To be fair, there are tools like GitHub Pages and Jekyll that serve websites based completely in Git repositories. These can be great for documentation websites or an engineering blog, but in general it's awkward for writers to deal with a VCS.

Ad tags, etc…

Ghost is wonderful for writing beautiful posts with Markdown. But I've been realizing that websites have many pieces that need to change regularly that aren't traditional post-type content—namely promotional content. On this blog and other sites I'm experimenting with display advertising, affiliate marketing systems, and promoting my own content. In the digital display advertising world, ad tags are the snippets of arbitrary HTML that website owners (publishers) add to their pages that result in ads or secondary content showing up in certain places. Larger publishers deal with tags from hundreds of sources, and their configurations need to change constantly. There are several systems meant just for managing these tags. As the owner of a small blog such a tool would be overkill, but I do feel the need to use something more frictionless than Git.

Unfortunately Ghost doesn't support inserting arbitrary content in user-defined sections, like Wordpress does. So I've been looking for a minimal CMS to use on top of Ghost, ideally with all of the following features:

  1. Support for arbitrary content types
  2. Revision control
  3. Secure, login-based editor
  4. Easy to set up
  5. Free

Today I used GitHub and 10 lines of JavaScript to implement a CMS with all of the above requirements! This is how I did it:

1. Create a GitHub Repository

We'll use the power of Git to manage our content. Git alone takes care of the first two requirements—we can save any filetype. With GitHub, we gain a secure, login-based editor. GitHub allows us to create and edit files from within the web UI, plus its editor is pleasant to write code with—a useful feature if we plan to include HTML or JavaScript files in our CMS.

In this initial design, the repo should have a single top-level directory called /tags, which will contain the bits of content that will be included in the website. The repo I created for this blog currently has a structure like:

/paislee-tags
|
|----/tags
|    |
|    |----home_top.html
|    |----post_top.html
|    |----post_bottom.html
|    |----sidebar_1.html
|    |----sidebar_2.html
|
|----README.md

Check out the GitHub repository here. The HTML files contain markup that I'd like to be "included" at various places in my website. Since these files are hosted on GitHub and publicly accessible, the trick is now to grab their contents and interpolate them in the right places.

2. Add some JavaScript to your Website

We can accomplish this with literally 10 lines of JavaScript. The code has one external dependency: jQuery. If you don't already use jQuery on your site, you can quickly pull in a CDN-hosted version:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>

Then include the following in your website's application JavaScript:

$(document).ready(function() {
    !function(config) {
        $('.paislee-tag').each(function() {
            var tagName = $(this).data('paislee-tag');
            $(this).load(config.prefix + tagName + '.html?cb=' + (new Date().getTime()));
        });
    }({
        prefix: 'https://raw.githubusercontent.com/paislee/paislee-tags/master/tags/'
    });
});

This code does the following;

For each <div class="paislee-tag"> element on the page:

  1. Get the value in the element's data-paislee-tag attribute.
  2. Fetch the corresponding raw HTML file from the GitHub repo defined in prefix, using a cache-buster to force refresh.
  3. Insert this HTML into the element with $.load().

That's all we need to support a minimal GitHub-based CMS!

3. Manage Content

Now, anywhere you'd like to include a block of managed content, add an element like the following, ensuring that the value of data-paislee-tag is the name of an HTML file in the GitHub repo /tags directory.

<div class="paislee-tag" data-paislee-tag="sidebar_1"></div>  

To update this content, simply log into GitHub, edit the file, and save (commit) it. Because of our cache-buster, changes will be reflected immediately.

At the time of writing, this is the code for the right-hand sidebar ad, courtesy of Google AdSense:

<!-- post_sidebar_1 -->  
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>  
<ins class="adsbygoogle"  
     style="display:block"
     data-ad-client="ca-pub-8556784045436185"
     data-ad-slot="9872978157"
     data-ad-format="auto"></ins>
<script>  
    (adsbygoogle = window.adsbygoogle || []).push({});
</script>  

The relevant file is visible under version control here.

Possible improvements

  1. Package and share — If people like this, or if I want to reuse it on other sites, I should make it an OSS project and publish to the Bower registry.
  2. Support more file-types — Currently it supports HTML, my main use case, but it'd be easy to extend to plain text, images and JavaScript.
  3. Private — GitHub repos are public unless you pay. There could be ways to make this work with a free private Git repo like BitBucket. GitHub Gists can be private, but do not expose a URL to the Gist's latest commit. See discussion here.

Anyway, this is completely meeting my needs for now! Your feedback is appreciated. Thanks.

Caleb Sotelo
AUTHOR

Caleb Sotelo

I'm a Software Engineer and Director of OpenX Labs. I try to write about software in a way that helps people truly understand it. Follow me @calebds.

View Comments