Automating Advent Calendar with Github Actions and Eleventy
Tags: webdev, javascript, eleventy, github
Published: 2023-01-16 17:21:38

---
canonical_url: https://eevis.codes/blog/2023-01-14/automating-advent-calendar-with-github-actions-and-eleventy/
---
I've always seen advent/Christmas calendars as an interesting, technical challenge. How to build something that hides content until some specified time? And to do that without client-side JavaScript? And automatically, so I don't need to deploy the page daily manually? 

This year, I decided to take up the challenge and build an advent calendar. After some consideration, the concept was clear: it would be in Finnish and about accessibility. I have a Finnish Instagram account where I talk about accessibility, so this combination made the most sense. 

After that, there was all the technical decisions and solving the problem above: How to keep content hidden until the right time? In this blog post, I'll share how I solved that problem. But first, let's look into the stack I chose to use.

## The Stack

The calendar is built with Eleventy - my go-to choice when I want to create something that's not so complicated that I need to break it into smaller components. Actually, now that I think of it, I'd still take Eleventy - my projects are usually simple. 

Other than that, I'm using plain CSS and no client-side JavaScript. I love how you can do that with Eleventy. So, if you're wondering how I'm doing "not showing the content before the correct date": No, it's not with JavaScript. It's a combination of Eleventy's features, a private repository, and Github Actions. Let's talk about them next.

## Hiding Content with Eleventy

I spent quite some time trying to come up with a solution that would solve my problem. I could have used client-side JavaScript, but then again, if I could solve that without it, it would be great.

So I started doing some research. Is there a way to prevent some pages from getting into the build Eleventy does? After searching with some terms that did not give me good results, I finally found the solution: `.eleventyignore` and having an `unpublished`-directory containing the unpublished content.

Yes, I felt a bit stupid after discovering this ignore file because that was not the first thing I thought. I mean, every JS project and package has one, so why didn't I think about it straight away? Well, that happens. I am sharing this because, usually, these blog posts are about results, not progress.

Back to the story, I now had a way to hide the following days. The next thing was to write a script to move the current day's content from one folder (`unpublished`) to another (`2022`).

As I've been using Node for many years, I used it for that. I could have gone with the shell commands, but my shell scripting skills are way rustier than Node skills, so I went with the easiest solution. 

After a while, I had a small function to handle moving the file. The function takes the current date as a parameter. It checks if the `unpublished` folder contains a file with that date and moves it to the `2022`-folder.

The next thing was to set up Github Action to run the script daily, commit it to the main branch and rebuild the site.

## Github Actions 

For the calendar app to work correctly, there were three noteworthy aspects of writing the Github Action file:
Running the workflow daily
Running the Node script mentioned in the previous section
Committing changes to the main branch. 

For running the workflow daily, I already had an example of a schedule-event with cron in another project, so that was a little copy-paste. [Github has good documentation around triggering events on workflows][1], and I wanted to run the workflow every night at 00:00 UTC, so these are the lines I used:

```yaml
  schedule:
    - cron:  '0 0 * * *'
```

The second task, running the Node script, was also straightforward. Defining the script in `package.json`´s scripts made it effortless to run in the workflow.

I used the shell scripts for the third task because I had an example of that in another project. I first defined the committers email and name with

```shell 
git config --global user.email "updater-bot"
git config --global user.name "updater-bot"
```

And after that, I added the moved files and committed them with
```shell
git add 2022 unpublished
git commit -m "Move day"
```

and finally pushed the branch to the main with

```shell
git push origin main
```

When the commit hit the main branch, the project got rebuilt, and the new changes were published.

## The Content

Writing the content was the most fun and time-consuming part of the project. I decided to go with three types of content: Information, task, and book recommendation. 

I ended up having 14 days of information, seven days of tasks, and three book recommendations. My goal was to gather material from different sources, with different types, and mainly in Finnish. And as I wanted to provide something new for a wider audience, I avoided technical content. 

## Sharing the Calendar

At the beginning of December, I shared the calendar on my social media accounts: Instagram and LinkedIn. The initial response was tremendous and showed in analytics; there was a clear spike in the visits to the page. Looking at the analytics, there were shares on (assumed) work settings, as some traffic came from Slack and Teams. 

After the initial sharing, I shared daily that day's content on my Instagram account. I could have advertised the calendar way more, but my December was so busy at work, and I didn't have the energy. It shows in the analytics; most of the traffic came from Instagram.

## Wrapping Up

This project was a fun one to complete. It was also the first web project I've created since switching to Android development, so I was interested in seeing if I'd totally forgotten how to web. I hadn't - but I still like Kotlin more than JavaScript 😅

Do you have technical challenges you've been thinking about for a longer time and want to solve? Or something seen as an intriguing challenge (but not necessarily wanting to solve yourself)?

[1]: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows