Using Hugo's resources and output formats to create favicons

Curious as to whether anyone in the community has come up with an easier partial, etc using Hugo’s image resizing (e.g. apple-touch-icon.png, favicon-32x32.png, etc) and output formats (e.g. site.webmanifest) so that it’s just a matter of dropping in a square image into assets or static and adding a couple params into config.*. Feel like this would come in really handy for creating a sorta boilerplate Hugo starter. Thanks ahead of time for anyone willing to share some code.

Note: I currently use https://realfavicongenerator.net/ to generate favicons, which is already pretty convenient, so please no recommendations for external services. I’m looking for something pure Hugo :smile:

2 Likes

Seconded!

I also think it would be an important addition to Hugo. With the way Hugo handles asset bundling/minification, it would be great to have favicon support as well and control it from the config file or within the theme partials.

Besides the ease-of-use, it’s especially important due to the fact that favicon management is cumbersome when you count in all the platforms and devices. Real Favicon Generator approaches this quite nice.

In my spare time, I’ll work on contributing to Hugo in that regard with the help of Real Favicon Generator’s non-interactive API.

Keep in mind I said it could be part of a starter kit and am not necessarily suggesting/requesting this become part of Hugo core :smile:

Yeah, I got it. It’s just a passion of mine and if(which is a big if) I can get around it with my current workload.

Resizing a 500px image into a 16x favicon rarely works right. You often have to adjust pixels in order for the human eye to see the right shape.

But you could define (hard coded or param) a slice of sizes and range through those. Upon finding an existing asset with the proper naming convention (size included), use its .Permalink.
Upon “not” finding it, resize the “original” asset to the size at hand and use that .Permalink. Keep ranging.

This way you could easily have one of the needed size ready, and the missing one generated by Hugo.

This can either by via Hugo Pipes or Page Resources (on the home bundle for instance)

I agree. That’s a good place to put if implemented. That was also what I had in mind.

Definitely. That’s why @rdwatters and I prefer https://realfavicongenerator.net since they overcome those issues by providing many options with inline previews.

If you go there and go through the process, you’ll see what I mean.

Of course, if implemented, Hugo would not have previews but just the end-result, however, it would significantly shorten the process.

And if anyone wants a preview of the end result, they can still go to the website to check them out.

But you could create a preview of those files somewhere. Simple custom layout page or Custom Ouput format on the home page.
This markup file (public) would show you all those generated sizes
If one does not suit, just drop a file with the correct filename (where you decided to store you files), and Hugo will know to use that file instead of Resizing.

I was looking for a way to have my favicon.ico processed as asset. Found nothing.
But I can give my setup for this thread.
I also use https://realfavicongenerator.net.

params.toml

# logo in /assets
logo  = "images/main_logo.png"

header.html

<!-- Favicon -->
<link rel="shortcut icon" type="image/x-icon" href='{{ "favicon.ico" | relURL }}'/>
<!-- Ces icones et fichiers sont générés sur realfavicongenerator.net
     et doivent être ajoutés manuellement dans /static/ -->
<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">

<!-- Gestion AUTOMATIQUE des divers apple-touch-icon.png en resources -->
{{- $path     := site.Params.logo }}
{{- $original := resources.Get $path  }}

{{- $apple_icon   := $original.Fit "76x76 png" }}
<link rel="apple-touch-icon-76x76" href="{{ $apple_icon.RelPermalink | relURL }}" />
<link rel="apple-touch-icon-76x76-precomposed" href="{{ $apple_icon.RelPermalink | relURL }}" />

{{- $apple_icon   := $original.Fit "114x114 png" }}
<link rel="apple-touch-icon" href="{{ $apple_icon.RelPermalink | relURL }}" />
<link rel="apple-touch-icon-precomposed" href="{{ $apple_icon.RelPermalink | relURL }}" />

{{- $apple_icon   := $original.Fit "120x120 png" }}
<link rel="apple-touch-icon-120x120" href="{{ $apple_icon.RelPermalink | relURL }}" />
<link rel="apple-touch-icon-120x120-precomposed" href="{{ $apple_icon.RelPermalink | relURL }}" />

{{- $apple_icon   := $original.Fit "128x128 png" }}
<!-- Pour android Chrome -->
<link rel="icon" type="image/png" href="{{ $apple_icon.RelPermalink | relURL }}" sizes=128x128>

{{- $apple_icon   := $original.Fit "152x152 png" }}
<link rel="apple-touch-icon-152x152" href="{{ $apple_icon.RelPermalink | relURL }}" />
<link rel="apple-touch-icon-152x152-precomposed" href="{{ $apple_icon.RelPermalink | relURL }}" />

{{- $apple_icon   := $original.Fit "160x160 png" }}
<link rel="apple-touch-icon-160x160" href="{{ $apple_icon.RelPermalink | relURL }}" />
<link rel="apple-touch-icon-160x160-precomposed" href="{{ $apple_icon.RelPermalink | relURL }}" />
<!-- Pour android Chrome -->
<link rel="icon" type="image/png" href="{{ $apple_icon.RelPermalink | relURL }}" sizes=160x160>

{{- $apple_icon   := $original.Fit "167x167 png" }}
<link rel="apple-touch-icon-167x167" href="{{ $apple_icon.RelPermalink | relURL }}" />
<link rel="apple-touch-icon-167x167-precomposed" href="{{ $apple_icon.RelPermalink | relURL }}" />

{{- $apple_icon   := $original.Fit "180x180 png" }}
<link rel="apple-touch-icon-180x180" href="{{ $apple_icon.RelPermalink | relURL }}" />
<link rel="apple-touch-icon-180x180-precomposed" href="{{ $apple_icon.RelPermalink | relURL }}" />

{{- $apple_icon   := $original.Fit "196x196 png" }}
<link rel="apple-touch-icon-196x196" href="{{ $apple_icon.RelPermalink | relURL }}" />
<link rel="apple-touch-icon-196x196-precomposed" href="{{ $apple_icon.RelPermalink | relURL }}" />

I found a way for Hugo to “generate” an ico but it’s really hacky. You need to place the png favicon in the asset directory, fetch it, resize it to 32x32 and create a resource from the resized image as favicon.ico.

    {{ $logo := resources.Get "192.png" }}
    {{ $sm := $logo.Resize "32x32" }}
    {{ $ico := $sm.Content | resources.FromString "/favicon.ico" }}
    <link rel="shortcut icon" href="{{ $ico.Permalink }}" type="image/x-icon">

As for what I do, I have a folder of favicons which are mounted to the assets directory. I also specify the favicons in the site’s config with their attributes and render them out.

#config.yml
params:
  theme-color: "#ffffff"
  favicons:
    - href: /favicon.ico
      sizes: 32x32
      rel: icon
    - href: /icon.svg
      rel: icon
      type: image/svg+xml
    - href: /apple-touch-icon.png
      rel: apple-touch-icon
      sizes: 180x180
    - href: /site.webmanifest
      rel: manifest
<!-- partials/favicons.html -->
{{ range site.Params.favicons }}
    <link{{ range $k, $v := . }}{{ printf " %s=%q" $k $v | safeHTMLAttr }}{{ end }}>
{{ end }}
{{ with site.Params.Get "theme-color" }}
    <meta name="theme-color" content="{{ . }}">
{{ end }}

As for the web manifest, you have something like this in the site’s config

output:
  home: [HTML, RSS, WebAppManifest]

Then you specify the manifest template in layouts/index.webmanifest.

1 Like