When I started at Doberman some two years ago, a new website project was just starting up. Our old site was, well, old. You know how it goes; the cobbler’s children and so on. Anyway, we designed and built a brand new site in Ruby on Rails complete with a custom CMS. We were this close to going live when we realized it wasn’t going to cut it. The problem—and you’re probably going to recognize this if you’ve built a few sites with CMS’s—was flexibility. Or rather the lack thereof. CMS’s are great for producing lots of content using a few predefined templates. And conversely, they’re terrible at sites that have loads of exceptions and unique content. Which is pretty much exactly what ours was all about.
Fast-forward about a year. Our old site was still up and we were getting desperate for a new one. The new website project was rebooted, and this time we were determined not to repeat the same old mistakes again. Instead, we were going to make brand new mistakes!
We were going to make brand new mistakes!
So, going into the new project, our main goal was flexibility. Each page would be like a single page site all on its own. And nothing was going to stand in our way. To give you a quick idea of what I’m talking about here, let’s take a look at a few pages:
As you can see, these three pages share virtually nothing; colors, typography and layout are all different.
Static is the new black
This extreme flexibility was unlike anything I had ever worked on. Nevertheless, we did have an idea on how to tackle it: use a static site generator combined with a cloud-based CMS service, build the site on a CI service and host it on a CDN. In other words, something like this:
Personally, I’ve long been a huge fan of static site generators. I’ve even built my own, that’s how much I love them. They have many advantages over a regular CMS:
- All the flexibilty
- If they break, they break on build, not unexpectedly in production
- They have a very small area of attack; there’s no database or backend framework to target
- They’re wicked fast
Now, I’m not going to lie and say there are no cons to a static site. Of course there are. The biggest one is most changes require development by an actual developer. We like developing stuff though, so I think we can live with that. The other big one is displaying dynamic content, like twitter feeds. Fortunately, Google launched the open beta of Firebase Functions—serverless micro-services—just as we were starting up our project. They’re awesome and you should try them out. They enable us to do all kind of fancy tricks with dynamic content, should we want to.
Turning it up to eleven
A static site lets us have unique content and markup for each page, but we wanted more. We wanted each page to have a unique look and on many pages, unique little pieces of script. Just for fun, you see. So we had each page have its own stylesheet and script files. This used to be a bad idea, but with HTTP/2 we can preload or even push assets along with the intial page request. Fantastic, right? We end up with a small core of styles and scripts and each page can load whatever extra stuff it needs.
A pretty neat side effect is building a new page on this site feels almost like building a tiny single page site. You know the feeling of starting something new, something fresh? Yeah, like that. Much better than feeling of wrestling with tonnes of legacy crap, right?
How it fits together
So how does this veritable ecosystem of libs and cloud services all fit together?
We keep the code on GitHub. Any content that’s editable by editors—contact information, news items, open jobs, what have you—is stored and edited on Contentful. We had good experiences with Jekyll so using it again was an easy choice, especially since there’s a plugin to pull data from Contentful. We build front-end assets, such as styles and scripts, with Gulp and a bunch of plugins; Babel, Rollup and Sass just to name a few. We switched CI service from Codeship to Travis CI for all our projects along the way, but both served well enough. For hosting, Firebase Hosting looked good with both HTTP/2 and CDN support. Considering we also needed to use Firebase Functions, or something like them, it was a great fit.
When code is pushed to GitHub or content is changed on Contentful, a new build is triggered on Travis CI. For Contentful, we use Firebase Functions as webhooks that in turn trigger a new build. Travis runs tests, pulls all editorial content from Contentful, builds the site and finally deploys to our preview and production environments. This way the site is automatically updated when someone creates new content or there are changes in the code, just as you’d expect.
How it turned out
The new site went live a couple of weeks ago at doberman.co. It’s been a smashing success. And by that I mean it’s pretty fast and it hasn’t crashed even once. Yet.
As usual, it’s not finished. Far from it; we have a pretty hefty backlog and some of the most fun parts had to be dropped towards the end because of browser compatibility issues. We haven’t abandoned it though, and we’re going to work continuously to add new features and improve the experience.
What we learned
So, here we are, at the tl;dr of this post. Personally, I learned a bunch of stuff about Jekyll and Contentful and how they work together. I had to build some custom content mappers and Liquid filters and tags. I also got to use Travis for real, having only used it for my personal projects before and never for deploying.
Looking at the slightly bigger picture, I think the main takeaway is that our initial hypothesis wasn’t half bad. A static site generator together with a standard cloud based CMS can do the same job as a server-based CMS such as Wordpress or Umbraco. And some things it does significantly better.