diff --git a/CHANGELOG.md b/CHANGELOG.md
index 10ba0cd..678b847 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
- **Smoother loading experience.** Pages now show a subtle preview of the layout while data loads instead of a blank screen or spinner. This applies everywhere — dashboards, settings, uptime, funnels, notifications, billing, and detail modals.
- **No more loading flicker.** Fast-loading pages no longer flash a loading state for a split second before showing content.
- **Clearer error messages.** When something goes wrong, the error message now tells you what failed (e.g. "Failed to load uptime monitors") instead of a generic "Failed to load data".
+- **Faster favicon loading.** Site icons in the dashboard, referrers, and campaigns now use Next.js image optimization for better caching and lazy loading.
## [0.10.0-alpha] - 2026-02-21
diff --git a/app/share/[id]/page.tsx b/app/share/[id]/page.tsx
index d645fe7..e1a32cc 100644
--- a/app/share/[id]/page.tsx
+++ b/app/share/[id]/page.tsx
@@ -1,6 +1,7 @@
'use client'
import { useCallback, useEffect, useState } from 'react'
+import Image from 'next/image'
import { useParams, useSearchParams, useRouter } from 'next/navigation'
import { getPublicDashboard, getPublicStats, getPublicDailyStats, getPublicRealtime, getPublicPerformanceByPage, type DashboardData, type Stats, type DailyStat, type PerformanceByPageStat } from '@/lib/api/stats'
import { toast } from '@ciphera-net/ui'
@@ -282,13 +283,16 @@ export default function PublicDashboardPage() {
Public Dashboard
-
{
(e.target as HTMLImageElement).src = '/globe.svg'
}}
+ unoptimized
/>
{site.domain}
diff --git a/components/dashboard/Campaigns.tsx b/components/dashboard/Campaigns.tsx
index f4b5f02..f15efd2 100644
--- a/components/dashboard/Campaigns.tsx
+++ b/components/dashboard/Campaigns.tsx
@@ -2,6 +2,7 @@
import { useState, useEffect, useMemo } from 'react'
import Link from 'next/link'
+import Image from 'next/image'
import { formatNumber } from '@ciphera-net/ui'
import { Modal, ArrowRightIcon, Button } from '@ciphera-net/ui'
import { TableSkeleton } from '@/components/skeletons'
@@ -111,11 +112,14 @@ export default function Campaigns({ siteId, dateRange }: CampaignsProps) {
const useFavicon = faviconUrl && !faviconFailed.has(source)
if (useFavicon) {
return (
-
setFaviconFailed((prev) => new Set(prev).add(source))}
+ unoptimized
/>
)
}
diff --git a/components/dashboard/TopReferrers.tsx b/components/dashboard/TopReferrers.tsx
index b4f0974..fbfca1a 100644
--- a/components/dashboard/TopReferrers.tsx
+++ b/components/dashboard/TopReferrers.tsx
@@ -1,6 +1,7 @@
'use client'
import { useState, useEffect } from 'react'
+import Image from 'next/image'
import { formatNumber } from '@ciphera-net/ui'
import { getReferrerDisplayName, getReferrerFavicon, getReferrerIcon, mergeReferrersByDisplayName } from '@/lib/utils/icons'
import { Modal, GlobeIcon } from '@ciphera-net/ui'
@@ -39,11 +40,14 @@ export default function TopReferrers({ referrers, collectReferrers = true, siteI
const useFavicon = faviconUrl && !faviconFailed.has(referrer)
if (useFavicon) {
return (
-
setFaviconFailed((prev) => new Set(prev).add(referrer))}
+ unoptimized
/>
)
}
diff --git a/components/sites/SiteList.tsx b/components/sites/SiteList.tsx
index fefa001..4cf70c1 100644
--- a/components/sites/SiteList.tsx
+++ b/components/sites/SiteList.tsx
@@ -1,6 +1,7 @@
'use client'
import Link from 'next/link'
+import Image from 'next/image'
import { Site } from '@/lib/api/sites'
import type { Stats } from '@/lib/api/stats'
import { formatNumber } from '@ciphera-net/ui'
@@ -34,10 +35,13 @@ function SiteCard({ site, stats, statsLoading, onDelete, canDelete }: SiteCardPr
-
diff --git a/next.config.ts b/next.config.ts
index 2bf94f0..484ecc8 100644
--- a/next.config.ts
+++ b/next.config.ts
@@ -12,6 +12,15 @@ const nextConfig: NextConfig = {
output: 'standalone',
// * Privacy-first: Disable analytics and telemetry
productionBrowserSourceMaps: false,
+ images: {
+ remotePatterns: [
+ {
+ protocol: 'https',
+ hostname: 'www.google.com',
+ pathname: '/s2/favicons**',
+ },
+ ],
+ },
async redirects() {
return [
{