Linus Heck

Posted on July 4, 2020

My new website in Hakyll

I made a new website, and as is tradition, once one makes a new website they have to post a blog post on how they made it or something. I used Hakyll, which I think is really nice. It’s basically a static site generator for Haskell fans which directly uses pandoc as a library. The only thing that might be interesting to you is how I made the projects page. The projects are just markdown files, and they have a coolness attribute after which they are sorted. Then, in the Hakyll compilation, I do this:

main :: IO ()
main = hakyll $ do
    [...]
    create ["index.html"] $ do
        route idRoute
        compile $ do
            projects <- reverse <$> (byCoolness =<< loadAll "projects/*/*.md")
            let blogCtx =
                    listField "projects" postCtx (return projects) `mappend`
                    constField "title" "Projects"                  `mappend`
                    defaultContext
            makeItem ""
                >>= loadAndApplyTemplate "templates/projects.html" blogCtx
                >>= loadAndApplyTemplate "templates/default.html" blogCtx
                >>= relativizeUrls
[...]

-- this parses the coolness out of an item
-- it defaults to 0 if it's missing, or can't be parsed as an Int
coolness :: MonadMetadata m => Item a -> m Int
coolness i = do
    mStr <- getMetadataField (itemIdentifier i) "coolness"
    return $ fromMaybe 0 (mStr >>= readMaybe)

byCoolness :: MonadMetadata m => [Item a] -> m [Item a]
byCoolness = sortByM coolness
  where
    sortByM :: (Monad m, Ord k) => (a -> m k) -> [a] -> m [a]
    sortByM f xs = fmap (map fst . sortBy (comparing snd)) $
                   mapM (\x -> liftM (x,) (f x)) xs

(This was written by a StackOverflow user for me because I’m too bad at Haskell :D).

Yeah, that’s about it. You can look at my website’s source code here if you want to.