How to schedule blog articles with GatsbyJS
Posted on: 2021-10-05
Coming from writing my blog articles on WordPress, I was rapidly disappointed that I couldn't write down a blog article in advance. Indeed, I could write the article without pushing to the master branch or leverage Git by creating a branch for each article and merge when ready to publish. However, I wanted to be able to write an article, set a date, maybe do some modification here and there, and forget about it. I wanted the article to be deployed automatically.
Each blog article has a header portion called frontmatter. The frontmatter has a date which is the date of the article. Thus, we can program some logic to only display articles before or equal to the frontmatter date.
The filtering needs to appear everywhere we have a list of articles. In my case, I have a list by year and a list that paginate all blog articles chronologically. The former GraphQL looks like this:
export const query = graphql`
query BlogsInYear($yearStart: Date!, $yearEnd: Date!, $currentDate: Date!) {
allMdx(
sort: { fields: frontmatter___date, order: DESC }
filter: {
frontmatter: {
date: { gte: $yearStart, lt: $yearEnd, lte: $currentDate }
}
}
) {
nodes {
frontmatter {
date(formatString: "MMMM D, YYYY")
title
categories
}
id
fields {
slug
}
}
}
}
`;
And the chronological pagingation:
export const query = graphql`
query TopXBlogArticles($limit: Int!, $skip: Int!, $currentDate: Date!) {
allMdx(
sort: { fields: frontmatter___date, order: DESC }
limit: $limit
skip: $skip
filter: { frontmatter: { date: { lte: $currentDate } } }
) {
nodes {
frontmatter {
date(formatString: "MMMM D, YYYY")
title
categories
}
id
fields {
slug
}
}
}
}
`;
As you can see, in both cases, we pass the $currentDate
. Here is the twist if you are new to GatsbyJS: the GraphQL is not dynamic in the client environment but when we build the whole website. Inside the gatsby-node.js
, in the createPages
function we are parsing the current date. Here is the code for the chronological per year page
const currentDate = new Date();
const formattedCurrentDate = currentDate.toISOString().split("T")[0];
const year = node.frontmatter.date.substr(0, 4);
if (!years.has(year)) {
const yearStart = year + "-01-01";
const yearEnd = year + 1 + "-01-01";
createPage({
path: URL_PER_YEAR.replace("{year}", year),
component: path.resolve(`./src/templates/BlogsByYear.tsx`),
context: {
yearStart: yearStart,
yearEnd: yearEnd,
year,
totalPages: totalPageCount,
currentDate: formattedCurrentDate,
},
});
years.set(year, year);
}
The last part is that once the code is sent in Github, there is a task to build the website and publish it. But the problem is that if I have an article with a release date in one week, the build needs to be executed on that specific day to have the code in the gatsby-node.js
to be executed to pass the currentDate
to the GraphQL query.
Thus, we need to alter our build script to trigger a build when the code or article changes and every day. It means that inside the .github/workflows/main.yml
the on
property changes to
on:
push:
branches: [master]
schedule:
- cron: '0 8 * * *'
The schedule
uses a cron
that executes every day at 8 UTC (which is during the night in the USA the build. So, in short, the whole website is built every day. The following picture shows how the Actions
tab looks, and you can see many Scheduled tasks and one commit by me (MrDesjardins), which is when I write and push the MardownX file.
To conclude, the possibility to schedule blog articles with GatsbyJS is possible. Like most features, it is not out-of-the-box but not a very excessive demanding workflow to implement.