
Automatically Publish Scheduled Posts For Your Static Site
Part of our mission at Forestry is to dissolve the perceived limitations of static sites. In reality, static sites are easy to understand and integrate with, and the belief that static sites are not capable of feature X is largely a failure of imagination. With a little cleverness and determination, virtually anything is possible on a static platform.
Previously, we showed you how to set up Algolia with Jekyll as well as with Hugo to make your content searchable. Today, we will tackle a basic feature of dynamic sites: publishing scheduled content. This article will present two options for achieving this:
- Extending your CircleCI configuration, for projects deployed via CircleCI
- Using a serverless function
The Old Way
Scheduling posts is easy when using a database-driven, backend-heavy CMS like WordPress: just enter the date and time you want to schedule the post, and click the “Schedule” button. Your post should automatically appear on the site once the date and time of the post have passed. You’re done!
Actually, hang on. If you’re using a page cache plugin (which is essential to keep the site running fast,) you will probably need to clear the cache once the post is published. Once you figure out how to clear the page cache at regular intervals, you can sit back and let your scheduled posts publish themselves automatically.
Ah, but maybe not. Sometimes WordPress will give you a Missed Schedule error and won’t publish the post! Go ahead and spend the rest of your day sorting that one out.
Maybe it’s not that easy.
Statelessness is Next to Godliness
Static sites are inherently stateless. They can’t respond to or even keep track of changes in state. The HTML payload delivered to a user can’t make decisions based on what time it is, or where the user is located. Everybody gets the same page, all the time.
This stateless nature makes our site very easy to understand and reason about. Our static site generator knows how to handle future posts by following a very simple algorithm during the build process:
If the post’s publish date is right now or some time in the past, build it into the site.
If not, leave it alone.
We can conceive of a very simple procedure for publishing posts in the future by ensuring that we automatically run this build process, and handle the subsequent deployment, at a regular interval.
Option 1: Scheduling Deployments with CircleCI
If you’re already using CircleCI to build and deploy your site, you can achieve this by adding a few extra lines to your CircleCI configuration at .circleci/config.yml
.
If you don’t have an automated build and deploy process for your static site, take a look at our tutorial on setting up an automatic static site deployment with CircleCI.
We can use CircleCI’s workflows feature to schedule recurring automatic deployment of our site. To do this, we just have to add a new section to our .circleci/config.yml
file with the following info:
workflows:
version: 2
build_test_deploy:
jobs:
- build
autopublish:
triggers:
- schedule:
cron: "0 */6 * * *"
filters:
branches:
only:
- master
jobs:
- build
This creates two workflows: one called build_test_deploy
, and one called autopublish
. We need to create the build_test_deploy
workflow to preserve the automatic deployment behavior, since CircleCI won’t do that by default if you have any workflows
defined.
The autopublish
workflow runs the same build
job, but we have configured it to run on a schedule using triggers
, and to only run this on the master branch.
The cron
parameter accepts crontab syntax to determine the interval between deployments. Our example deploys every 6 hours. Feel free to tweak this to suit your publishing schedule.
Option 2: Using a Lambda Task to Trigger Your Build
If you are using a different deployment solution, such as deploying from Forestry, I have developed a more generic solution.
serverless-autopublish is an AWS Lambda task built with the serverless framework. Its purpose is very simple: it pushes a new commit to your GitHub repository at regular intervals. This will trigger any automated deployment you have configured as if you were updating the site manually.
Installation
Follow the serverless framework AWS quick start to install the framework and connect it to your AWS account.
AWS Lambda has a generous free tier that allows up to 400,000 CPU seconds of usage every month before you start incurring charges. If you run this task 4 times a day, you will stay within the free tier as long as the task completes in under an hour. (That’s a really long time.)
Depending on the size of your repos, publishing can take several seconds. However, you can cap the execution time of your function: I have set it to 15 seconds, which is plenty of time for most use cases.
Usage
This serverless function is written in Go, and uses the fantastic go-git library. The project includes the compiled binaries for the AWS Lambda environment, so you don’t need to have Go installed on your machine to deploy it.
To get started, you can either fork the repo or initialize a new serverless project with this template:
serverless create --template-url https://github.com/dwalkr/serverless-autopublish --path serverless-autopublish
Once the project is created, open the serverless-autopublish
directory. The serverless.yml
file is where you will configure your function. When you open it, you will see something like this:
functions:
publish:
handler: bin/publish
timeout: 15
events:
- schedule: rate(6 hours)
environment:
github_token: ${ssm:github_token}
author_name: your-author-name
author_email: your-author-email
repos: https://github.com/FIRST-REPO;https://github.com/SECOND-REPO
This configuration defines a function called publish
that will run every hour. You can adjust this by modifying the schedule
parameter.
The variables in the environment
section are passed to the function as environment variables. This is how we will configure the publisher. Change author_name
and author_email
to your desired Git signature, and add the repositories you want to publish to the repos
variable. Separate multiple repos with a semicolon.
Adding Your Github Access Token
In order to authenticate with your Github account, you need to provide the function with an access token (Github: creating a personal access token). Serverless provides functionality to retrieve values from the AWS Systems Manager Parameter Store, and our configuration will look for the token in here.
Log in to AWS and locate the Systems Manager service. Select Parameter Store and create a new parameter. The parameter name will be github_token
and the value will be the token you requested from Github. Once your token is in Parameter Store, Serverless will automatically add it to your serverless.yml
configuration when you deploy it.
Deploy and Run
After you’re satisfied with your configuration, run the following command to send your function to AWS:
serverless deploy
After the command finishes, your function is live! You can expect your repos to start receiving commits according to the schedule you configured in the serverless.yml
file. You can run the function immediately with the following command:
serverless invoke -f publish
If you want to remove your function from AWS, use the remove
command:
serverless remove
Go Beyond
Our scheduled post solution is pretty basic, but effective. Using strategies like serverless functions and build automation, we can start to reimagine what static sites are capable of.
Join us every Friday 📅
Frontend Friday is a weekly series where we write in-depth posts about modern web development.
Next week: We'll look at what's new in the latest Jekyll update.
Last week: We showed you how to use Create Static Site to bootstrap a production-ready static site project.
Have something to add?
Caught a mistake or want to contribute to the blog? Edit this page on Github!