Hugo Favicon Complete Guide

Master favicon setup in Hugo: static folder configuration, partial templates, config file settings, and best practices for the world's fastest static site generator.

Hugo Favicon Setup (3 Steps)

1. Static Folder

Place in static/

2. Create Partial

Template for <head>

3. Include Partial

Add to base template

Step 1: Static Folder Setup

File Structure

my-hugo-site/
  static/
    favicon.ico           ? Place all favicons here
    favicon-16x16.png
    favicon-16x16.png
    favicon-32x32.png
    favicon-96x96.png
    favicon-512x512.png
    apple-touch-icon.png
    android-chrome-192x192.png
    android-chrome-512x512.png
    site.webmanifest
  layouts/
    partials/
      head.html
      favicon.html        ? Create this
    _default/
      baseof.html
  config.toml
  content/
  themes/
Note: Files in static/ are copied to public/ at root level during build. Accessible at https://yoursite.com/favicon.ico

Step 2: Create Favicon Partial

layouts/partials/favicon.html

Basic Favicon Partial

<!-- Favicon -->
<link rel="icon" type="image/x-icon" href="/favicon.ico">
<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="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="manifest" href="/site.webmanifest">
<meta name="theme-color" content="#ffffff">

Advanced Partial with Config

{{- $faviconPath := .Site.Params.faviconPath | default "/" -}}

<!-- Favicon -->
<link rel="icon" type="image/x-icon" href="{{ $faviconPath }}favicon.ico">
<link rel="icon" type="image/png" sizes="32x32" href="{{ $faviconPath }}favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="{{ $faviconPath }}favicon-16x16.png">

<!-- Apple Touch Icon -->
<link rel="apple-touch-icon" sizes="180x180" href="{{ $faviconPath }}apple-touch-icon.png">

<!-- Android/Chrome -->
<link rel="icon" type="image/png" sizes="192x192" href="{{ $faviconPath }}android-chrome-192x192.png">
<link rel="icon" type="image/png" sizes="512x512" href="{{ $faviconPath }}android-chrome-512x512.png">

<!-- Web App Manifest -->
<link rel="manifest" href="{{ $faviconPath }}site.webmanifest">

<!-- Theme Color -->
<meta name="theme-color" content="{{ .Site.Params.themeColor | default "#ffffff" }}">

{{- if .Site.Params.safariPinnedTab -}}
<link rel="mask-icon" href="{{ $faviconPath }}pinned-tab.svg" color="{{ .Site.Params.safariPinnedTabColor | default "#5bbad5" }}">
{{- end -}}

{{- if .Site.Params.msTileColor -}}
<meta name="msapplication-TileColor" content="{{ .Site.Params.msTileColor }}">
<meta name="msapplication-TileImage" content="{{ $faviconPath }}ms-icon-144x144.png">
{{- end -}}

config.toml Settings

[params]
  faviconPath = "/"
  themeColor = "#FF4088"
  safariPinnedTab = true
  safariPinnedTabColor = "#FF4088"
  msTileColor = "#FF4088"

Step 3: Include in Base Template

layouts/_default/baseof.html

<!DOCTYPE html>
<html lang="{{ .Site.Language.Lang }}">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    
    <title>{{ block "title" . }}{{ .Site.Title }}{{ end }}</title>
    
    {{- partial "favicon.html" . -}}
    
    {{ block "head" . }}{{ end }}
  </head>
  <body>
    {{ block "main" . }}{{ end }}
  </body>
</html>
That's it! The {{- partial "favicon.html" . -}} line includes your favicon code on every page.

Advanced Hugo Features

Dynamic & Conditional Favicons

Environment-Specific Favicons

{{- if hugo.IsProduction -}}
  <link rel="icon" type="image/x-icon" href="/favicon.ico">
{{- else -}}
  <link rel="icon" type="image/x-icon" href="/favicon-dev.ico">
{{- end -}}

Per-Section Favicons

{{- $faviconName := "favicon.ico" -}}

{{- if eq .Section "blog" -}}
  {{- $faviconName = "favicon-blog.ico" -}}
{{- else if eq .Section "docs" -}}
  {{- $faviconName = "favicon-docs.ico" -}}
{{- end -}}

<link rel="icon" type="image/x-icon" href="/{{ $faviconName }}">

Front Matter Override

Content file:

---
title: "My Page"
favicon: "/custom-favicon.ico"
---

Template:

{{- $favicon := .Params.favicon | default "/favicon.ico" -}}
<link rel="icon" type="image/x-icon" href="{{ $favicon }}">

Build & Deploy

Production Build

Build Commands

# Development server
hugo server -D
# Test at http://localhost:1313

# Production build
hugo --minify
# Output in public/ folder

# Clean build
rm -rf public/ && hugo --minify

Verify Build

  1. Check public/ folder contains favicon files
  2. Open public/index.html and search for "favicon"
  3. Verify paths are correct (no double slashes)
  4. Test locally: cd public && python3 -m http.server

Deployment Platforms

  • Netlify: Auto-detects Hugo, deploys public/
  • Vercel: Configure build command: hugo --minify
  • GitHub Pages: Use GitHub Actions for Hugo build
  • Cloudflare Pages: Native Hugo support

Hugo Favicon Best Practices

? Best Practices

  • Place all favicons in static/ folder
  • Create reusable partial template
  • Use config.toml for customization
  • Leverage Hugo variables/conditionals
  • Test with hugo server
  • Use --minify for production
  • Verify build output in public/
  • Use Hugo pipes for optimization

? Common Mistakes

  • Placing favicons in assets/ or layouts/
  • Forgetting trailing/leading slashes in paths
  • Not using Hugo variables for flexibility
  • Hardcoding paths instead of config
  • Not testing production build locally
  • Missing partial in baseof.html
  • Wrong path when using baseURL subdirectory
  • Not clearing public/ folder before rebuild

Generate Hugo-Ready Favicons

Create optimized favicon packages for Hugo static sites

Generate Favicons

Related Articles

An unhandled error has occurred. Reload 🗙