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