Skip to Main Content

How my site is built with Eleventy + Ghost

First iteration, 2019

In the beginning of 2019, I started building this website and decided to use Eleventy as my static site generator. I got the template from HTML5Up (love it) and started making things happen.

I chose Eleventy mostly because a friend was using it as well and following him work on his site got me curious. I haven't really taken full advantage of its features yet but one day I'll dive deeper into components and such. The ability to write my own collection functions, template filters and helper functions in Javascript is a really big plus for me.

Originally, this blog was a collection of posts written in Markdown but writing posts in Markdown became bit of a burden and I ended up not writing anything. I missed a good editor experience. Maybe it's because I write code in my editor and writing blog posts requires a very different thinking process or maybe it was just a good excuse I came up with for not writing more.

The improvement

(I did a talk in HelsinkiJS about this process in January)

Last December, I was listening to the Indie Hackers Podcast episode where Ghost founder John O'Nolan was discussing Ghost. I had looked at Ghost earlier some years ago but never ended up using it. Now the time was right, and I like the not-for-profit model and open source approach so I decided to investigate how to integrate Ghost with my existing Eleventy site.

I found a blog post Use Eleventy To Generate A Ghost Blog by David Darnes which gave me hope that it wouldn't take me months to build. I installed Ghost on my local dev machine and started building the integration.

Thanks to the Ghost ContentAPI, getting data from my Ghost instance was easy but other things turned out to be a bit of a challenge. First of all, I had old posts written in Markdown and new posts written in Ghost and combining those two wasn't easy. They had different data models and I was running a bit in circles trying to match them.

Second, creating posts in localhost meant that all the pictures were also hosted on that instance. So I built a function as part of my build process that downloaded all the pictures from posts and fixed the references. Somehow, it ended up also messy because Eleventy kept re-building every time it downloaded a picture and ended up in an endless loop in development mode.

Last, hosting the Ghost in my localhost and bundling fetching the posts as part of the build process turned out to be very problematic. It meant that doing any changes into the site or copy outside the blog required fetching all posts and I could only do that with one computer.

Second iteration, 2020

So last week I decided to redo it. Here's where we are now:

I moved Ghost to a Digital Ocean VPS so I can edit anywhere with any computer. I decoupled post fetching from the build process into a separate Node script. Everytime I want to get posts, I run npm run fetch which turns Ghost posts into Markdown files and stores them alongside my older Markdown posts. I'm not 100% sure if that's the best idea but it solved another of my problems: different data models. And I can now edit the copy or layout without having to fetch all the posts on every save.

By saving the Ghost posts as a Markdown files, I can also keep the files in my version control and everything doesn't horribly break if something happens to my Ghost instance.

All together, the new version feels much more robust. I'm still not sure if saving Ghost posts as Markdown files is the best approach but it's a big improvement.

Redirects

Oh, one more thing. I built a redirect layout template which allows me to do easy redirects like https://hamatti.org/youtube and have them do a 301 redirect to wherever I want. It's not exactly a short url service but it serves a similar function.

<!doctype html>
<html>
  <head>
    <meta http-equiv="Refresh" content="0; url="/>
  </head>
</html></code>