Publish Blog Posts on a static website using GitHub Actions


Static websites are great. They offer high performance, and low operating costs by converting your source code into a static website just once at build time. But, what if you want to write articles in advance and have them become available automatical when the publish date and time occures?

In this example, we will publish a static AstroJS site hourly using a combination of filters in our template, and a build hook triggered by GitHub actions.

Filtering posts

const filterOutUnpublished = (array: any[]) => {
  return array.filter((item: any) => new Date(item.data.date) <= new Date());
};
const posts = await getCollection('blog');
const publishedPosts = filterOutUnpublished(posts);

This works by using JavaScript’s filter method on an array of posts, that will return a new array containging only posts where the test - in this case checking the date is now or in the past - returns true.

Your theme might already have a filter for publishing future posts, but if it doesn’t then take a look for how it handles draft posts and drop the filter in there.

Once you are set up to only build publish posts, the next challenge is trigger the build periodically so they appear automatically once their published date passes.

To do this, most providers will offer a way to enable a deploy hook: A url that you can call to trigger a deploy. Once you have a deploy hook, you can configure Github actions to use a scheduled cron job using the workflow-webhook to hit the url on a regular basis to rebuild the site.

name: Deploy every hour
 
on:
  schedule:
    - cron: '0 * * * *'
jobs:
  daily-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: distributhor/workflow-webhook@v3
        with:
          webhook_url: https://my-static-host/build-url

In this example, every hour a rebuild will be triggered. You should modify the frequency of the builds to reflect the limits of your provider. For instance, CloudFlare limit you 500 deploys a month, Netlify’s free tier limits you to 300 minutes.

Personally, I deploy every four hours using this format.

on:
  schedule:
    - cron: '0 0/4 * * *'

You can use a tool like Crontab Guru if you’re not sure of the cron syntax.

While it might seem wasteful to be building your site every hour, remember that in a dynamic site it gets rendered on every single page view.