Sticky/Pinned posts in Hakyll

Posted on December 25, 2025
Categories (1):

Sticky posts come from my MyOpera blogging days. They bring a bit of nostalgia, because I used that feature quite heavily back when I was on that platform.

And finally, I’ve added them to my Hakyll setup.

Here is the code snippet:

--site.hs
....
-- get the sticky flag from the front matter and mark posts that are sticky
isSticky :: Metadata -> Bool
isSticky = maybe False (=="true") . lookupString "sticky"

-- Split the posts into sticky posts and normal posts
splitStickyPosts
    :: [Item String]
    -> Compiler ([Item String], [Item String])
splitStickyPosts items = do
    let ident = itemIdentifier

    stickies <- filterM (fmap isSticky . getMetadata . ident) items
    normals  <- filterM (fmap (not . isSticky) . getMetadata . ident) items

    stickies' <- recentFirst stickies
    normals'  <- recentFirst normals

    return (stickies', normals')
    
-- I currently want to show sticky posts only in the index so I made the change accordingly

match "index.html" $ do
            route idRoute
            compile $ do
                (stickies, posts) <- splitStickyPosts allPosts
                let hasStickies = if null stickies then False else True
                let indexCtx =
                                listField "stickies" postCtx (return stickies) `mappend`
                                boolField "hasStickies" (const hasStickies) `mappend`
                                listField "posts"    postCtx (return (take 4 posts)) `mappend`
                                constField "title" "Decidedly Confused Thoughts" `mappend`
                                defaultContext

                getResourceBody
                    >>= applyAsTemplate indexCtx
                    >>= loadAndApplyTemplate "templates/default.html" indexCtx
                    >>= relativizeUrls
<!-- index.html -->
$partial("templates/stickies.html")$
<!-- stickies.html -->
$if(hasStickies)$
<section class="stickies">
    <h2>📌 Pinned</h2>
    <ul>
        $for(stickies)$
        <li>
            <a href="$postLink$">$title$</a>
        </li>
        $endfor$
    </ul>
</section>
$endif$