A blog about stuff but also things.
The fun thing about having a blog which is built with a static site
generator is that you get to waste spend time customising it. In today's instalment of "Hacking the blog", we'll see how to add a "favicon", which is that little icon thingy on your tab title.
My first order of business was to figure out what I wanted to use for my favicon. I decided that I really love this drawing that my friend Sebastian did on a whiteboard way back in 2016, so why not use it?

The first step (after I remembered what a "favicon" was actually called) was making a clean version of this image that would scale down nicely to the various sizes used by browsers. Courtesy of a really thorough answer to a question on Stack Overflow, I found a really cool site called RealFaviconGenerator, which would take an image (recommended to be at least 260x206 pixels) and spit out a zipfile containing a bunch of files:
These files, if placed at the root of your website and combined with a chunk of HTML in your <head> section, would do the right thing for All the Browsers and All the Smartphones.
So I opened up my image in the GIMP, cropped it so only my head was visible, and removed the speech bubble, resulting in the following:

I fed this image into RealFaviconGenerator, which gave me back the zipfile described above and the following HTML fragment:
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">
The next order of business was to get the favicon onto my site. If you remember from the Actually blogging with Clojure post, the way the blog works is this:
bb.edn which defines a render task that looks like this:render {:doc "Render blog"
:task (load-file "render.clj")}
render.clj does stuff like converting Markdown to HTML, then uses the Selmer templating system to shove blog posts into the templates/base.html templaterender.clj then copies the resulting HTML files to a public/ directorypublish in bb.edn that uses the AWS CLI to sync everything in the public/ to the S3 bucket that contains my blog:publish {:doc "Publish to jmglov.net"
:depends [render]
:task (shell "aws s3 sync --delete public/ s3://jmglov.net/blog/")}
So getting the favicon injected into every page was as simple as blasting the HTML fragment into templates/base.html.
Almost.
You see, I also need to put the content being referenced in all of those <link> tags up on the website. My website itself uses the exact same machinery as the blog, meaning I need to add the HTML fragment to the top-level templates/base.html, and in order to get the favicon stuff onto the website, I need to hack up the top-level render.clj.
Looking at the way the existing render.clj (which I stole with pride from borkdudeโs blog) handles images and CSS is most instructive:
(def out-dir "public")
;;;; Sync images and CSS
(def asset-dir (fs/create-dirs (fs/file out-dir "assets")))
(fs/copy-tree "assets" asset-dir {:replace-existing true})
(spit (fs/file out-dir "style.css")
(slurp "templates/style.css"))
Since the deploy task will sync everything from the public/ directory to my website, I just need to put the contents of the favicon zipfile in public/ and I win!
I unzipped the favicon zipfile into a top-level favicon/ directory, then added the following to render.clj:
;;;; Sync favicon
(def favicon-dir (fs/create-dirs (fs/file out-dir)))
(fs/copy-tree "favicon" favicon-dir {:replace-existing true})
And that's all it took to display my little cartoon face on your browser's tab! ๐
If you're interested, you can check out this commit to see everything I did, all wrapped up into one cute little package.