From fbd05641332387e13c0655443544daa6fbc85388 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Fri, 23 Jan 2026 19:33:39 -0800 Subject: [PATCH 1/5] Add x-umami-client-* headers as highest priority source for client detection. --- src/lib/detect.ts | 10 ++++++++-- src/lib/ip.ts | 3 ++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/lib/detect.ts b/src/lib/detect.ts index 68cb6672..6af61b78 100644 --- a/src/lib/detect.ts +++ b/src/lib/detect.ts @@ -10,6 +10,12 @@ import { safeDecodeURIComponent } from '@/lib/url'; const MAXMIND = 'maxmind'; const PROVIDER_HEADERS = [ + // Umami custom headers + { + countryHeader: 'x-umami-client-country', + regionHeader: 'x-umami-client-region', + cityHeader: 'x-umami-client-city', + }, // Cloudflare headers { countryHeader: 'cf-ipcountry', @@ -60,13 +66,13 @@ function decodeHeader(s: string | undefined | null): string | undefined | null { return Buffer.from(s, 'latin1').toString('utf-8'); } -export async function getLocation(ip: string = '', headers: Headers, hasPayloadIP: boolean) { +export async function getLocation(ip: string = '', headers: Headers, skipHeaders: boolean) { // Ignore local ips if (!ip || (await isLocalhost(ip))) { return null; } - if (!hasPayloadIP && !process.env.SKIP_LOCATION_HEADERS) { + if (!skipHeaders && !process.env.SKIP_LOCATION_HEADERS) { for (const provider of PROVIDER_HEADERS) { const countryHeader = headers.get(provider.countryHeader); if (countryHeader) { diff --git a/src/lib/ip.ts b/src/lib/ip.ts index 5cd77574..b4c46573 100644 --- a/src/lib/ip.ts +++ b/src/lib/ip.ts @@ -1,4 +1,5 @@ export const IP_ADDRESS_HEADERS = [ + 'x-umami-client-ip', // Umami custom header 'true-client-ip', // CDN 'cf-connecting-ip', // Cloudflare 'fastly-client-ip', // Fastly @@ -31,7 +32,7 @@ export function getIpAddress(headers: Headers) { } if (header === 'forwarded') { - const match = ip.match(/for=(\[?[0-9a-fA-F:.]+\]?)/); + const match = ip.match(/for=(\[?[0-9a-fA-F:.]+]?)/); if (match) { return match[1]; From fd2e2047cdf400da1deccec062a570ed1540b4d5 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Fri, 23 Jan 2026 20:30:42 -0800 Subject: [PATCH 2/5] Restrict x-umami-client-* headers to cloud mode only. --- src/lib/detect.ts | 16 ++++++++++------ src/lib/ip.ts | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/lib/detect.ts b/src/lib/detect.ts index 6af61b78..e713ecf7 100644 --- a/src/lib/detect.ts +++ b/src/lib/detect.ts @@ -10,12 +10,16 @@ import { safeDecodeURIComponent } from '@/lib/url'; const MAXMIND = 'maxmind'; const PROVIDER_HEADERS = [ - // Umami custom headers - { - countryHeader: 'x-umami-client-country', - regionHeader: 'x-umami-client-region', - cityHeader: 'x-umami-client-city', - }, + // Umami custom headers (cloud mode only) + ...(process.env.CLOUD_MODE + ? [ + { + countryHeader: 'x-umami-client-country', + regionHeader: 'x-umami-client-region', + cityHeader: 'x-umami-client-city', + }, + ] + : []), // Cloudflare headers { countryHeader: 'cf-ipcountry', diff --git a/src/lib/ip.ts b/src/lib/ip.ts index b4c46573..f6ee733b 100644 --- a/src/lib/ip.ts +++ b/src/lib/ip.ts @@ -1,5 +1,5 @@ export const IP_ADDRESS_HEADERS = [ - 'x-umami-client-ip', // Umami custom header + ...(process.env.CLOUD_MODE ? ['x-umami-client-ip'] : []), // Umami custom header (cloud mode only) 'true-client-ip', // CDN 'cf-connecting-ip', // Cloudflare 'fastly-client-ip', // Fastly From 9b310dacef01080845c6c9e01f4888ba8ce04f0b Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Thu, 29 Jan 2026 01:00:23 -0800 Subject: [PATCH 3/5] Remove events section from share page overview Share page overview should look the same as normal app overview Co-Authored-By: Claude Opus 4.5 --- .../websites/[websiteId]/WebsitePanels.tsx | 24 +------------------ 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/src/app/(main)/websites/[websiteId]/WebsitePanels.tsx b/src/app/(main)/websites/[websiteId]/WebsitePanels.tsx index a91d562e..4a666f10 100644 --- a/src/app/(main)/websites/[websiteId]/WebsitePanels.tsx +++ b/src/app/(main)/websites/[websiteId]/WebsitePanels.tsx @@ -1,15 +1,13 @@ import { Grid, Heading, Row, Tab, TabList, TabPanel, Tabs } from '@umami/react-zen'; import { GridRow } from '@/components/common/GridRow'; import { Panel } from '@/components/common/Panel'; -import { useMessages, useNavigation } from '@/components/hooks'; -import { EventsChart } from '@/components/metrics/EventsChart'; +import { useMessages } from '@/components/hooks'; import { MetricsTable } from '@/components/metrics/MetricsTable'; import { WeeklyTraffic } from '@/components/metrics/WeeklyTraffic'; import { WorldMap } from '@/components/metrics/WorldMap'; export function WebsitePanels({ websiteId }: { websiteId: string }) { const { formatMessage, labels } = useMessages(); - const { pathname } = useNavigation(); const tableProps = { websiteId, limit: 10, @@ -18,7 +16,6 @@ export function WebsitePanels({ websiteId }: { websiteId: string }) { metric: formatMessage(labels.visitors), }; const rowProps = { minHeight: '570px' }; - const isSharePage = pathname.includes('/share/'); return ( @@ -116,25 +113,6 @@ export function WebsitePanels({ websiteId }: { websiteId: string }) { - {isSharePage && ( - - - {formatMessage(labels.events)} - - - - - - - - )} ); } From abfb78bb980ea078d6110738c24bf315221be4fb Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Thu, 29 Jan 2026 09:23:53 -0800 Subject: [PATCH 4/5] Fixed mobile menus. --- src/app/(main)/MobileNav.tsx | 2 +- src/app/share/[slug]/[[...path]]/ShareNav.tsx | 6 +++--- src/components/input/MobileMenuButton.tsx | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app/(main)/MobileNav.tsx b/src/app/(main)/MobileNav.tsx index aaa25846..a9d9e861 100644 --- a/src/app/(main)/MobileNav.tsx +++ b/src/app/(main)/MobileNav.tsx @@ -42,7 +42,7 @@ export function MobileNav() { {({ close }) => { return ( <> - + {links.map(link => { return ( diff --git a/src/app/share/[slug]/[[...path]]/ShareNav.tsx b/src/app/share/[slug]/[[...path]]/ShareNav.tsx index e6ca3865..db927afe 100644 --- a/src/app/share/[slug]/[[...path]]/ShareNav.tsx +++ b/src/app/share/[slug]/[[...path]]/ShareNav.tsx @@ -144,12 +144,12 @@ export function ShareNav({ position={isMobile ? undefined : 'fixed'} padding="3" width={isMobile ? '100%' : collapsed ? '60px' : '240px'} - maxHeight="100vh" - height="100vh" + maxHeight="100dvh" + height="100dvh" border={isMobile ? undefined : 'right'} borderColor={isMobile ? undefined : '4'} > - + {!collapsed && ( diff --git a/src/components/input/MobileMenuButton.tsx b/src/components/input/MobileMenuButton.tsx index 8498b05a..a4713ae0 100644 --- a/src/components/input/MobileMenuButton.tsx +++ b/src/components/input/MobileMenuButton.tsx @@ -9,7 +9,7 @@ export function MobileMenuButton(props: DialogProps) { - + From e57239de1e7b0c965420a59fcf9a5b88dc45a300 Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Thu, 29 Jan 2026 10:13:08 -0800 Subject: [PATCH 5/5] Fix share parameter logic --- src/app/share/[slug]/[[...path]]/ShareNav.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/share/[slug]/[[...path]]/ShareNav.tsx b/src/app/share/[slug]/[[...path]]/ShareNav.tsx index db927afe..11cc2f9b 100644 --- a/src/app/share/[slug]/[[...path]]/ShareNav.tsx +++ b/src/app/share/[slug]/[[...path]]/ShareNav.tsx @@ -129,7 +129,7 @@ export function ShareNav({ const items = allItems .map(section => ({ label: section.label, - items: section.items.filter(item => parameters[item.id] !== false), + items: section.items.filter(item => parameters[item.id] === true), })) .filter(section => section.items.length > 0);