Gatsby Favicon Complete Guide
Master favicon setup in Gatsby: static folder configuration, gatsby-plugin-manifest, React Helmet integration, GraphQL queries, and best practices for React-based static sites.
Gatsby Favicon Setup
1. Static Folder
Place in static/
2. Plugin Setup
Configure manifest plugin
3. React Helmet
Add to layout component
Method 1: Static Folder (Recommended)
Simplest Approach
File Structure
my-gatsby-site/
static/
favicon.ico ? Place here
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
src/
components/
layout.js
seo.js
pages/
index.js
gatsby-config.jsNote: Files in
static/ are copied to public/ during build and accessible at root URL (e.g., /favicon.ico).
SEO Component with React Helmet
File: src/components/seo.js
import React from 'react'
import { Helmet } from 'react-helmet'
import { useStaticQuery, graphql } from 'gatsby'
function SEO({ title, description }) {
const { site } = useStaticQuery(
graphql`
query {
site {
siteMetadata {
title
description
}
}
}
`
)
const metaDescription = description || site.siteMetadata.description
return (
<Helmet>
<title>{title} | {site.siteMetadata.title}</title>
<meta name="description" content={metaDescription} />
{/* Favicons */}
<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="#663399" />
</Helmet>
)
}
export default SEOUse in Layout
File: src/components/layout.js
import React from 'react'
import SEO from './seo'
const Layout = ({ children, pageTitle, pageDescription }) => {
return (
<>
<SEO title={pageTitle} description={pageDescription} />
<main>{children}</main>
</>
)
}
export default LayoutMethod 2: gatsby-plugin-manifest
PWA-Ready Setup
Install Plugin
npm install gatsby-plugin-manifestConfigure gatsby-config.js
module.exports = {
siteMetadata: {
title: 'My Gatsby Site',
description: 'A Gatsby site with proper favicons',
siteUrl: 'https://mygatsby.com',
},
plugins: [
'gatsby-plugin-react-helmet',
{
resolve: 'gatsby-plugin-manifest',
options: {
name: 'My Gatsby Site',
short_name: 'Gatsby Site',
start_url: '/',
background_color: '#ffffff',
theme_color: '#663399',
display: 'standalone',
icon: 'src/images/icon.png', // Source image (512x512 or higher)
icons: [
{
src: '/android-chrome-192x192.png',
sizes: '192x192',
type: 'image/png',
},
{
src: '/android-chrome-512x512.png',
sizes: '512x512',
type: 'image/png',
},
],
// Optional: Generate different sizes
icon_options: {
purpose: 'any maskable',
},
// Include favicon in head section
include_favicon: true,
// Legacy support
legacy: true,
// Cache busting mode
cache_busting_mode: 'query',
// Crossorigin attribute
crossOrigin: 'use-credentials',
},
},
],
}Important:
gatsby-plugin-manifest automatically generates multiple icon sizes from the source icon image. Provide a high-resolution PNG (512x512 or larger).
What the Plugin Generates
- ? Multiple favicon sizes (16x16, 32x32, 48x48, etc.)
- ? Apple Touch Icons (120x120, 152x152, 167x167, 180x180)
- ? Android Chrome icons (192x192, 512x512)
- ?
manifest.webmanifestfile - ? Automatic
<link>tags in<head>
Advanced Configuration
Custom Favicon Paths
Using GraphQL for Dynamic Favicons
import React from 'react'
import { Helmet } from 'react-helmet'
import { useStaticQuery, graphql } from 'gatsby'
function SEO({ title }) {
const data = useStaticQuery(graphql`
query {
site {
siteMetadata {
title
siteUrl
}
}
favicon32: file(relativePath: { eq: "favicon-32x32.png" }) {
publicURL
}
favicon16: file(relativePath: { eq: "favicon-16x16.png" }) {
publicURL
}
appleTouchIcon: file(relativePath: { eq: "apple-touch-icon.png" }) {
publicURL
}
}
`)
return (
<Helmet>
<title>{title}</title>
<link rel="icon" type="image/png" sizes="32x32" href={data.favicon32.publicURL} />
<link rel="icon" type="image/png" sizes="16x16" href={data.favicon16.publicURL} />
<link rel="apple-touch-icon" href={data.appleTouchIcon.publicURL} />
</Helmet>
)
}
export default SEOEnvironment-Specific Favicons
import React from 'react'
import { Helmet } from 'react-helmet'
function SEO() {
const isDev = process.env.NODE_ENV === 'development'
const faviconPath = isDev ? '/favicon-dev.ico' : '/favicon.ico'
return (
<Helmet>
<link rel="icon" type="image/x-icon" href={faviconPath} />
</Helmet>
)
}
export default SEODark Mode Favicon
<Helmet>
<link
rel="icon"
href="/favicon-light.svg"
type="image/svg+xml"
media="(prefers-color-scheme: light)"
/>
<link
rel="icon"
href="/favicon-dark.svg"
type="image/svg+xml"
media="(prefers-color-scheme: dark)"
/>
</Helmet>Build & Deploy
Production Deployment
Build Process
# Development
gatsby develop
# Favicons available at http://localhost:8000/favicon.ico
# Production build
gatsby build
# Files copied from static/ to public/
# Test production build locally
gatsby serve
# Test at http://localhost:9000Verify After Build
- Check
public/folder contains all favicon files - Verify
public/manifest.webmanifestexists - Check HTML files have favicon
<link>tags - Test in browser:
http://localhost:9000/favicon.ico
Deployment Platforms
| Platform | Favicon Handling | Notes |
|---|---|---|
| Netlify | ? Automatic | Deploys public/ folder |
| Vercel | ? Automatic | Static files served from root |
| Gatsby Cloud | ? Optimized | CDN-served favicons |
| GitHub Pages | ? Supported | Update pathPrefix if needed |
Gatsby Favicon Best Practices
? Best Practices
- Use
static/folder for all favicons - Install
gatsby-plugin-manifestfor PWA - Use React Helmet for dynamic
<head> - Provide high-res source image (512x512+)
- Test build output in
public/folder - Use GraphQL queries for dynamic paths
- Cache bust with
gatsby clean - Test on multiple browsers after deploy
? Common Mistakes
- Placing favicons in
src/instead ofstatic/ - Forgetting to run
gatsby buildto test - Not using
gatsby-plugin-manifestfor PWA - Missing React Helmet plugin
- Using low-resolution source images
- Not clearing cache (
.cache/folder) - Incorrect paths in production (missing
/) - Not testing favicon after deployment
Generate Gatsby-Ready Favicons
Create optimized favicon packages for Gatsby static sites
Generate Favicons