Slik legger du til favicon i Next.js-prosjektet ditt: Komplett implementeringsguide for 2025
Favicons er avgjørende for moderne webapplikasjoner — de vises i nettleserfaner, bokmerker, mobile hjemmeskjermer og PWA-installasjoner. Next.js tilbyr flere implementeringsmetoder avhengig av ruterkonfigurasjonen og funksjonskravene dine.
Denne omfattende guiden gir deg alt du trenger for å implementere profesjonelle favicon-systemer i Next.js-prosjekter, fra grunnleggende oppsett til avanserte dynamiske funksjoner.
Hva du vil lære:
- Next.js 13+ App Router favicon-implementering
- Eldre Pages Router-kompatibilitetsmetoder
- Dynamiske favicon-oppdateringer og tematilpasning
- PWA- og flerenhetsoptimalisering
- Ytelsesoptimalisering og feilsøking
- Praktiske kodeeksempler og beste praksis
Hurtigstart: Grunnleggende favicon-oppsett (5 minutter)
Steg 1: Generer favicon-filene dine
Anbefalt verktøy: Bruk RealFaviconGenerator eller Favicon.io for profesjonelle resultater.
Anbefalt filstruktur:
public/
├── favicon.ico # Universell kompatibilitet (16x16, 32x32)
├── favicon-16x16.png # Nettleserfaner (eldre støtte)
├── favicon-32x32.png # Høyoppløselige nettleserfaner
├── apple-touch-icon.png # 180x180 (iOS-hjemmeskjerm)
├── android-chrome-192x192.png # Android-hjemmeskjerm
├── android-chrome-512x512.png # PWA og høyoppløselige skjermer
└── site.webmanifest # Progressive Web App-manifest
Steg 2: Umiddelbart grunnleggende oppsett
Nullkonfigurasjonsmetode: Plasser favicon.ico i public-katalogen. Next.js serverer den automatisk på /favicon.ico.
Rask verifisering: Besøk http://localhost:3000/favicon.ico for å bekrefte at filen er tilgjengelig.
Next.js 13+ App Router-implementering
Metode 1: Metadata API-konfigurasjon (anbefalt)
Hvorfor denne metoden: Typesikker, innebygd Next.js-støtte, automatisk optimalisering, bedre SEO.
Next.js App Router støtter filbasert favicon-konfigurasjon:
// app/layout.tsx
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'My Next.js App',
description: 'Amazing Next.js application',
icons: {
icon: '/favicon.ico',
shortcut: '/favicon-16x16.png',
apple: '/apple-touch-icon.png',
},
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
Metode 2: Profesjonell flerenhetskonfigurasjon
For produksjonsklare applikasjoner med omfattende plattformstøtte:
// app/layout.tsx
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'My Next.js App',
description: 'Amazing Next.js application',
// Omfattende favicon-konfigurasjon
icons: {
// Primære nettleserikoner
icon: [
{ url: '/favicon-16x16.png', sizes: '16x16', type: 'image/png' },
{ url: '/favicon-32x32.png', sizes: '32x32', type: 'image/png' },
],
// Eldre ICO-støtte
shortcut: '/favicon.ico',
// iOS-hjemmeskjermikoner
apple: [
{ url: '/apple-touch-icon.png', sizes: '180x180', type: 'image/png' },
],
// Android- og PWA-ikoner
other: [
{
rel: 'icon',
url: '/android-chrome-192x192.png',
sizes: '192x192',
type: 'image/png'
},
{
rel: 'icon',
url: '/android-chrome-512x512.png',
sizes: '512x512',
type: 'image/png'
},
],
},
// PWA-manifest for app-lignende opplevelse
manifest: '/site.webmanifest',
// Ekstra mobiloptimalisering
other: {
'theme-color': '#000000',
'msapplication-TileColor': '#000000',
}
}
Metode 3: Dynamisk favicon-generering
Avansert brukstilfelle: Dynamiske favicons basert på brukerkontekst, miljø eller applikasjonstilstand.
// app/layout.tsx
import { headers } from 'next/headers'
import type { Metadata } from 'next'
export async function generateMetadata(): Promise<Metadata> {
const headersList = headers()
const userAgent = headersList.get('user-agent') || ''
// Miljøbasert favicon-valg
const isDevelopment = process.env.NODE_ENV === 'development'
const isMobile = /Mobile|Android|iPhone/i.test(userAgent)
// Dynamisk favicon-logikk
let faviconPath = '/favicon.ico'
if (isDevelopment) {
faviconPath = '/favicon-dev.ico' // Utviklingsindikator
} else if (isMobile) {
faviconPath = '/favicon-mobile.ico' // Mobiloptimalisert versjon
}
return {
title: 'My Next.js App',
icons: {
icon: faviconPath,
apple: '/apple-touch-icon.png',
},
// Ekstra dynamisk metadata
other: {
'theme-color': isDevelopment ? '#ff6b6b' : '#000000',
}
}
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
Eldre Pages Router-implementering (Next.js 12 og lavere)
Metode 1: Komponentnivå-implementering med next/head
Best for: Sidespesifikke favicons eller når du trenger ulike favicons for ulike ruter.
// pages/_app.tsx
import Head from 'next/head'
import type { AppProps } from 'next/app'
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<Head>
<link rel="icon" href="/favicon.ico" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="manifest" href="/site.webmanifest" />
<meta name="theme-color" content="#000000" />
</Head>
<Component {...pageProps} />
</>
)
}
Metode 2: Global implementering med Custom Document (anbefalt)
Best for: Applikasjonsomfattende favicon-konfigurasjon som gjelder for alle sider.
// pages/_document.tsx
import { Html, Head, Main, NextScript } from 'next/document'
export default function Document() {
return (
<Html lang="en">
<Head>
{/* Essensielle nettleserikoner */}
<link rel="icon" href="/favicon.ico" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
{/* Mobilenhetikoner */}
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="192x192" href="/android-chrome-192x192.png" />
<link rel="icon" type="image/png" sizes="512x512" href="/android-chrome-512x512.png" />
{/* PWA- og plattformkonfigurasjon */}
<link rel="manifest" href="/site.webmanifest" />
<meta name="theme-color" content="#000000" />
<meta name="msapplication-TileColor" content="#000000" />
<meta name="msapplication-config" content="/browserconfig.xml" />
{/* Ekstra SEO- og mobiloptimalisering */}
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
Avanserte implementeringer
Dynamiske favicon-oppdateringer
Opprett en tilpasset hook for dynamiske favicon-oppdateringer:
// hooks/useFavicon.ts
import { useEffect } from 'react'
export const useFavicon = (faviconUrl: string) => {
useEffect(() => {
const link = document.querySelector("link[rel*='icon']") as HTMLLinkElement ||
document.createElement('link')
link.type = 'image/x-icon'
link.rel = 'shortcut icon'
link.href = faviconUrl
if (!document.querySelector("link[rel*='icon']")) {
document.getElementsByTagName('head')[0].appendChild(link)
}
}, [faviconUrl])
}
// Bruk i komponent
export default function MyComponent() {
const [theme, setTheme] = useState('light')
useFavicon(theme === 'dark' ? '/favicon-dark.ico' : '/favicon-light.ico')
return (
<button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
Toggle Theme
</button>
)
}
Varslingsmerke-favicon
Opprett et varslingssystem med favicon-merker:
// components/NotificationFavicon.tsx
import { useEffect, useRef } from 'react'
interface NotificationFaviconProps {
count: number
originalFavicon?: string
}
export const NotificationFavicon: React.FC<NotificationFaviconProps> = ({
count,
originalFavicon = '/favicon-32x32.png'
}) => {
const canvasRef = useRef<HTMLCanvasElement>(null)
useEffect(() => {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
canvas.width = 32
canvas.height = 32
const img = new Image()
img.onload = () => {
if (!ctx) return
// Tegn originalt favicon
ctx.drawImage(img, 0, 0, 32, 32)
if (count > 0) {
// Tegn varslingsmerke
ctx.fillStyle = '#ff4444'
ctx.beginPath()
ctx.arc(24, 8, 8, 0, 2 * Math.PI)
ctx.fill()
// Tegn antall-tekst
ctx.fillStyle = 'white'
ctx.font = 'bold 10px Arial'
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
ctx.fillText(count > 9 ? '9+' : count.toString(), 24, 8)
}
// Oppdater favicon
const link = document.querySelector("link[rel*='icon']") as HTMLLinkElement ||
document.createElement('link')
link.type = 'image/png'
link.rel = 'shortcut icon'
link.href = canvas.toDataURL()
if (!document.querySelector("link[rel*='icon']")) {
document.getElementsByTagName('head')[0].appendChild(link)
}
}
img.src = originalFavicon
}, [count, originalFavicon])
return null
}
// Bruk
export default function App() {
const [notifications, setNotifications] = useState(0)
return (
<>
<NotificationFavicon count={notifications} />
<button onClick={() => setNotifications(notifications + 1)}>
Add Notification ({notifications})
</button>
</>
)
}
Tematilpasset favicon
Implementer favicon som tilpasser seg systemtemaet:
// components/ThemeAdaptiveFavicon.tsx
import { useEffect, useState } from 'react'
export const ThemeAdaptiveFavicon = () => {
const [isDark, setIsDark] = useState(false)
useEffect(() => {
// Sjekk systempreferanse
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
setIsDark(mediaQuery.matches)
// Lytt etter endringer
const handleChange = (e: MediaQueryListEvent) => {
setIsDark(e.matches)
}
mediaQuery.addEventListener('change', handleChange)
return () => mediaQuery.removeEventListener('change', handleChange)
}, [])
useEffect(() => {
const faviconUrl = isDark ? '/favicon-dark.ico' : '/favicon-light.ico'
const link = document.querySelector("link[rel*='icon']") as HTMLLinkElement ||
document.createElement('link')
link.type = 'image/x-icon'
link.rel = 'shortcut icon'
link.href = faviconUrl
if (!document.querySelector("link[rel*='icon']")) {
document.getElementsByTagName('head')[0].appendChild(link)
}
}, [isDark])
return null
}
// Bruk i _app.tsx eller layout.tsx
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<ThemeAdaptiveFavicon />
<Component {...pageProps} />
</>
)
}
Web Manifest-konfigurasjon
Opprett et komplett web-manifest for PWA-støtte:
// public/site.webmanifest
{
"name": "My Next.js App",
"short_name": "NextApp",
"description": "Amazing Next.js application",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#000000",
"background_color": "#ffffff",
"display": "standalone",
"start_url": "/",
"scope": "/"
}
Favicon-generering ved byggetidspunkt
Automatiser favicon-generering under bygging:
// scripts/generate-favicons.js
const sharp = require('sharp')
const fs = require('fs')
const sizes = [
{ size: 16, name: 'favicon-16x16.png' },
{ size: 32, name: 'favicon-32x32.png' },
{ size: 180, name: 'apple-touch-icon.png' },
{ size: 192, name: 'android-chrome-192x192.png' },
{ size: 512, name: 'android-chrome-512x512.png' }
]
async function generateFavicons() {
const inputFile = 'assets/logo.png'
for (const { size, name } of sizes) {
await sharp(inputFile)
.resize(size, size)
.png()
.toFile(`public/${name}`)
console.log(`Generated ${name}`)
}
// Generer ICO-fil
await sharp(inputFile)
.resize(32, 32)
.toFile('public/favicon.ico')
console.log('Generated favicon.ico')
}
generateFavicons().catch(console.error)
// package.json
{
"scripts": {
"generate-favicons": "node scripts/generate-favicons.js",
"build": "npm run generate-favicons && next build"
}
}
Vanlige problemer og løsninger
Problem 1: Favicon oppdateres ikke under utvikling
Problem: Nettleseren mellomlagrer gammelt favicon under utvikling
Løsning:
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
async headers() {
return [
{
source: '/favicon.ico',
headers: [
{
key: 'Cache-Control',
value: process.env.NODE_ENV === 'development'
? 'no-cache, no-store, must-revalidate'
: 'public, max-age=31536000, immutable',
},
],
},
]
},
}
module.exports = nextConfig
Problem 2: Favicon mangler i produksjon
Problem: Statiske filer serveres ikke riktig
Løsning:
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
async rewrites() {
return [
{
source: '/favicon.ico',
destination: '/favicon.ico',
},
]
},
}
module.exports = nextConfig
Problem 3: Flere favicon-formater lastes ikke
Problem: Komplekst favicon-oppsett forårsaker konflikter
Løsning: Bruk en prioritetsbasert tilnærming:
// components/FaviconManager.tsx
import Head from 'next/head'
export const FaviconManager = () => {
return (
<Head>
{/* Høy prioritet: Moderne nettlesere */}
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
{/* Middels prioritet: PNG-reserveløsning */}
<link rel="icon" type="image/png" href="/favicon-32x32.png" />
{/* Lav prioritet: Eldre ICO */}
<link rel="shortcut icon" href="/favicon.ico" />
{/* Mobilspesifikt */}
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
<link rel="manifest" href="/site.webmanifest" />
</Head>
)
}
Testing av favicon-implementeringen din
Sjekkliste for utviklingstesting
- [ ] Favicon vises i nettleserfaner
- [ ] Favicon vises i bokmerker
- [ ] Mobil «Legg til på hjemmeskjerm» fungerer
- [ ] PWA-installasjonsikon er korrekt
- [ ] Tilpasning til mørk/lys modus (hvis implementert)
Profesjonelle testverktøy
1. Favicon.im - Umiddelbar validering
- Rask favicon-utpakking og testing
- Kompatibilitetssjekk på tvers av plattformer
- Identifisering av manglende størrelser
- Best for: Rask validering og feilsøking
2. RealFaviconGenerator Checker - Omfattende analyse
- Detaljert plattformspesifikk testing
- PWA-samsvarsverifisering
- Ytelsesanbefalinger
- Best for: Profesjonelle revisjoner og optimalisering
3. Browser DevTools - Teknisk feilsøking
- Nettverksfanen for lastingsproblemer
- Konsollefeil for manglende filer
- Applikasjonsfanen for manifest-inspeksjon
- Best for: Teknisk feilsøking og ytelsesanalyse
Manuelle teststeg
- Tøm nettleserbufferen
- Besøk nettstedet ditt i inkognitomodus
- Test på ulike enheter
- Verifiser bokmerkeutseende
- Test «Legg til på hjemmeskjerm»-funksjonaliteten
Ytelsesoptimalisering
Filstørrelsesoptimalisering
# Optimaliser PNG-filer
pngquant --quality=65-80 --output favicon-optimized.png favicon.png
# Optimaliser ICO-filer
convert favicon.png -resize 32x32 -colors 256 favicon.ico
HTTP-bufringshoder
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
async headers() {
return [
{
source: '/:path(favicon.ico|.*\\.png)',
headers: [
{
key: 'Cache-Control',
value: 'public, max-age=31536000, immutable',
},
],
},
]
},
}
module.exports = nextConfig
Komplett implementeringssjekkliste
Fase 1: Grunnleggende oppsett
- [ ] Generer favicon-filer ved hjelp av RealFaviconGenerator eller Favicon.io
- [ ] Plasser filer i public-katalogen med korrekt navngivning
- [ ] Velg implementeringsmetode (App Router vs Pages Router)
- [ ] Grunnleggende HTML-oppsett med essensielle link-tagger
- [ ] Test grunnleggende funksjonalitet på tvers av store nettlesere
Fase 2: Flerenhetsoptimalisering
- [ ] iOS-hjemmeskjermstøtte (180x180 apple-touch-icon)
- [ ] Android-kompatibilitet (192x192 og 512x512 ikoner)
- [ ] PWA-manifestkonfigurasjon for app-lignende opplevelse
- [ ] Windows-flisstøtte med riktige meta-tagger
- [ ] Temafarge-integrasjon for mobile nettlesere
Fase 3: Avanserte funksjoner (valgfritt)
- [ ] Dynamiske favicon-oppdateringer med tilpassede hooks
- [ ] Tematilpassede ikoner for lys/mørk modus
- [ ] Varslingsmerker for sanntidsoppdateringer
- [ ] Ytelsesoptimalisering med bufringshoder
- [ ] Byggetidsgenerering med automatiserte skript
Viktige implementeringsstrategier
For moderne Next.js-prosjekter (13+)
Anbefalt: Bruk App Router med metadata.icons API for typesikker, optimalisert favicon-håndtering.
For eldre prosjekter (12 og lavere)
Anbefalt: Implementer i _document.tsx for global dekning med next/head for sidespesifikke behov.
For dynamiske applikasjoner
Avansert: Kombiner statisk oppsett med kjøretidsoppdateringer ved hjelp av tilpassede hooks og canvas-manipulering.
For PWA-applikasjoner
Essensielt: Inkluder omfattende manifestkonfigurasjon med flere ikonstørrelser og riktige meta-tagger.
Endelige anbefalinger
Start enkelt: Begynn med grunnleggende ICO + PNG-oppsett, og utvid basert på behov
Bruk profesjonelle verktøy: RealFaviconGenerator for omfattende dekning
Test grundig: Valider på tvers av nettlesere, enheter, og bruk Favicon.im for rask testing
Optimaliser ytelse: Implementer riktige bufringshoder og komprimer favicon-filer
Planlegg for vekst: Design favicon-systemet ditt for å kunne håndtere fremtidige funksjoner som varsler og tematilpasning
Ved å følge denne omfattende guiden vil du skape et profesjonelt favicon-system som forbedrer brukeropplevelsen, styrker merkevaregjenkjenning og fungerer sømløst på alle moderne enheter og nettlesere.
Use favicon.im to quickly check if your favicon is configured correctly. Our free tool ensures your website's favicon displays properly across all browsers and devices.
Free Public Service
Favicon.im is a completely free public service trusted by developers worldwide.