Forgive the somewhat clunky title - I wanted to share a little demo I built for my presentation this week at DevNexus. The idea behind the demo was whether or not I could create a simple dynamic calendar system with a static web site. My presentation was all about adding dynamic aspects back into a static site, so this fit right in.

For the demo, I made use of FullCalendar. FullCalendar is a simple little jQuery plugin that renders a nice full screen (well, "as big as you want it") calendar. It can be driven by Google Calendar which is one simple way of adding a dynamic calendar to a static site, but I wanted to try something a bit different.

I began by creating a new Jekyll site (which is a bit of a pain on Windows). Jekyll has a feature called Collections which allow you to define a basic "content type" for your site. By default, Jekyll has a "Post" collection already built in. Jekyll is primarily used for blogs. But you can create your own collections for whatever makes sense for your site.

I began by defining a collection called events. This is done in _config.yml

    output: true
    permalink: /events/:path/
    title: Events

I specified that I wanted my events to be published as pages and that they should use a URL path of /events/X, where X is based on the file name.

I added a new directory called _events and wrote my first piece of content:

layout: event
title:  "Ray's Birthday"
event_date:   2017-4-8

Let's gather together to celebrate Raymond's birthday!

In a real page I'd have a lot more content about the event (possibly) but pay attention to the front matter. I've got a layout and title which is pretty standard, but event_date is custom. As you can probably guess, this represents the date of the event itself. I made a second page and then verified that they were rendering ok in my site.

I didn't spend a lot of time on the template, but it works, so I'm down with it.

Now came the interesting part. How do I get these random event pages available in FullCalendar? Here is where some static site generators shine - and some drop the ball. The SSG I used for my blog, Hugo, makes it incredibly difficult (imo) to add ad hoq pages with custom logic. You have to make a page with next to no input, tell it to use a layout that has the code, and then work over there instead of the page itself. I've seen multiple SSGs do this whereas both Jekyll and Harp are much more open in this regard.

I created my JSON data by adding a new file,, with this code:

permalink: /calendar-data/

{% for event in %}
		"start": "{{event.event_date}}",
	{%unless forloop.last %},{%end unless%}
{% endfor %}

I've specified no layout and title. This keeps the output clean and the "page" invisible from the top header. I then output over my collection data which Jekyll makes available via The only kind weird part is the {% unless %} block. That's how I handle including a comma between each event item and not after the last one. The end result was a JSON feed available at /calendar-data/ that looked like this:


		"title":"Carol's Birthday",
		"start": "2017-3-07",

		"title":"Ray's Birthday",
		"start": "2017-4-8",


It could be formatted a bit nicer, but it works. I then added a new page to render the FullCalendar:

layout: page
title: Event Calendar
permalink: /calendar/

<script src=""   
integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8="  crossorigin="anonymous"></script>
<script type="text/javascript" src="/scripts/moment.min.js"></script>
<script src="//"></script>
<link rel="stylesheet" href="//">
<link rel="stylesheet" media="print" href="//">

$(document).ready(function() {




<div id="calendar"></div>

FullCalendar supports a lot of customizations, but all I did was specify the URL where the event data could be found. Here it is in action:

So yeah, not exactly rocket science, but I've been wanting to build this for a while. This approach would not scale to a huge amount of events, but you could build out events in a "per month" or "per year" file to keep things sensible. FullCalendar can use a function to define how to load data, so you could dynamically create a URL path to the proper data feed based on what month is being requested.

You can find the full source for this demo here: