Components structure in Umami codebase - Part 1.4
Inspired by BulletProof React, I applied its codebase architecture concepts to the Umami codebase.
This article focuses only on the components structure in Umami codebase.

Prerequisite
-
Components structure in Umami codebase — Part 1.0
-
Components structure in Umami codebase — Part 1.1
-
Components structure in Umami codebase — Part 1.2
-
Components structure in Umami codebase — Part 1.3
In the parts 1.0–1.2, we reviewed the /websites route components structure. In the part 1.3, we reviewed the components structure in /websites/[websiteId], this article is in continuation to part 1.3 where review the website detail page. We will look at:
WebsiteMetricsBar
You will find the following code defined in WebsiteMetricsBar
import { useDateRange, useMessages } from '@/components/hooks';
import { MetricCard } from '@/components/metrics/MetricCard';
import { MetricsBar } from '@/components/metrics/MetricsBar';
import { formatShortTime, formatLongNumber } from '@/lib/format';
import { useWebsiteStatsQuery } from '@/components/hooks/queries/useWebsiteStatsQuery';
import { LoadingPanel } from '@/components/common/LoadingPanel';
export function WebsiteMetricsBar({
websiteId,
}: {
websiteId: string;
showChange?: boolean;
compareMode?: boolean;
}) {
const { isAllTime } = useDateRange();
const { formatMessage, labels, getErrorMessage } = useMessages();
const { data, isLoading, isFetching, error } = useWebsiteStatsQuery(websiteId);
const { pageviews, visitors, visits, bounces, totaltime, comparison } = data || {};
const metrics = data
? [
{
value: visitors,
label: formatMessage(labels.visitors),
change: visitors - comparison.visitors,
formatValue: formatLongNumber,
},
{
value: visits,
label: formatMessage(labels.visits),
change: visits - comparison.visits,
formatValue: formatLongNumber,
},
{
value: pageviews,
label: formatMessage(labels.views),
change: pageviews - comparison.pageviews,
formatValue: formatLongNumber,
},
{
label: formatMessage(labels.bounceRate),
value: (Math.min(visits, bounces) / visits) * 100,
prev: (Math.min(comparison.visits, comparison.bounces) / comparison.visits) * 100,
change:
(Math.min(visits, bounces) / visits) * 100 -
(Math.min(comparison.visits, comparison.bounces) / comparison.visits) * 100,
formatValue: n => Math.round(+n) + '%',
reverseColors: true,
},
{
label: formatMessage(labels.visitDuration),
value: totaltime / visits,
prev: comparison.totaltime / comparison.visits,
change: totaltime / visits - comparison.totaltime / comparison.visits,
formatValue: n =>
`${+n < 0 ? '-' : ''}${formatShortTime(Math.abs(~~n), ['m', 's'], ' ')}`,
},
]
: null;
return (
<LoadingPanel
data={metrics}
isLoading={isLoading}
isFetching={isFetching}
error={getErrorMessage(error)}
minHeight="136px"
>
<MetricsBar>
{metrics?.map(({ label, value, prev, change, formatValue, reverseColors }) => {
return (
<MetricCard
key={label}
value={value}
previousValue={prev}
label={label}
change={change}
formatValue={formatValue}
reverseColors={reverseColors}
showChange={!isAllTime}
/>
);
})}
</MetricsBar>
</LoadingPanel>
);
}
You will see the imports from
-
components/hooks
-
components/metrics
-
components/common
WebsitePanels
WebsitePanels component has about 140 LOC at the time of writing this article. We also see the imports happening same as above:
-
components/hooks
-
components/metrics
-
components/common

WebsiteControls
WebsiteControls has the following definition
import { Column, Row, Grid } from '@umami/react-zen';
import { WebsiteFilterButton } from '@/components/input/WebsiteFilterButton';
import { WebsiteDateFilter } from '@/components/input/WebsiteDateFilter';
import { FilterBar } from '@/components/input/FilterBar';
import { MonthFilter } from '@/components/input/MonthFilter';
import { ExportButton } from '@/components/input/ExportButton';
export function WebsiteControls({
websiteId,
allowFilter = true,
allowDateFilter = true,
allowMonthFilter,
allowDownload = false,
allowCompare = false,
}: {
websiteId: string;
allowFilter?: boolean;
allowDateFilter?: boolean;
allowMonthFilter?: boolean;
allowDownload?: boolean;
allowCompare?: boolean;
}) {
return (
<Column gap>
<Grid columns={{ xs: '1fr', md: 'auto 1fr' }} gap>
<Row alignItems="center" justifyContent="flex-start">
{allowFilter ? <WebsiteFilterButton websiteId={websiteId} /> : <div />}
</Row>
<Row alignItems="center" justifyContent={{ xs: 'flex-start', md: 'flex-end' }}>
{allowDateFilter && (
<WebsiteDateFilter websiteId={websiteId} allowCompare={allowCompare} />
)}
{allowDownload && <ExportButton websiteId={websiteId} />}
{allowMonthFilter && <MonthFilter />}
</Row>
</Grid>
{allowFilter && <FilterBar websiteId={websiteId} />}
</Column>
);
}
All the components used in this WebsiteControls are imported from components/input folder.
About me:
Hey, my name is Ramu Narasinga. I study codebase architecture in large open-source projects.
Email: ramu.narasinga@gmail.com
I spent 200+ hours analyzing Supabase, shadcn/ui, LobeChat. Found the patterns that separate AI slop from production code. Stop refactoring AI slop. Start with proven patterns. Check out production-grade projects at thinkthroo.com