Adding `published` to Hakyll Posts

Posted on May 18, 2020 by Riccardo.

Last week I deployed the blog and published by mistake a post that I was keeping for the future:

I guess that was just a matter of time cause I always keep some unpublished posts around. Up until now, I was doing some hacky manual git stuff to schedule them. Not anymore!

I added support for an additional published field in the metadata of each post. The scaffolding script now adds published: false by default.

The core of the change resides in site.hs:

-  match "posts/*" $ do
+  matchMetadata "posts/*" isPublished $ do

In particular, instead of compiling all posts, it only takes the “published” ones. A post is considered published if

  1. it does not have a published metadata field or
  2. published is true.

I could have enforced all posts to have a published field and skip 1. but I was too lazy to retrofit that 😅

Here’s the implementation:

isPublished :: Metadata -> Bool
isPublished = maybe True (== "true") . lookupString "published"

I actually did one step more and decided to consider all posts published when a HAKYLL_ENV env variable is set to development:

env <- getEnvironment
hakyll $ do
  matchMetadata "posts/*" (isDevelopmentOrPublished env) $ do
-- ...

isDevelopmentOrPublished :: [(String, String)] -> Metadata -> Bool
isDevelopmentOrPublished env metadata = isDevelopmentEnv || isPublished
  where
    isDevelopmentEnv = lookup "HAKYLL_ENV" env == Just "development"
    isPublished = maybe True (== "true") . lookupString "published" $ metadata

That way, as long as I preview the blog with HAKYLL_ENV=development stack exec site watch, I can keep published: false while working on a new post.

Please feel free to copy the code described above and use it for your Hakyll blog!


I need your help to make the blog awesome. Here's a survey. Since there are no required questions, you decide how much time to spend on it.

Support my work by tweeting this article! 🙏