Skip to content

Commit e984e20

Browse files
authored
feat(app): theme-based branding in UI copy (#1768)
## Summary Replace hardcoded "HyperDX" in user-facing UI with the current theme's display name so deployments using the ClickStack theme show "ClickStack" (e.g. "Welcome to ClickStack", "ClickStack Cloud") instead of "HyperDX". Closes HDX-3463. ## Changes ### Theme - **ThemeProvider**: Add `useBrandDisplayName()` hook that returns `theme.displayName` ("HyperDX" or "ClickStack") for use in copy. ### Pages & layout - **Auth**: Login/register page title and brand label use `useBrandDisplayName()`. - **AuthLoadingBlocker**: "Loading HyperDX" → "Loading {brandName}". - **JoinTeamPage**: Document title uses brand name. - **LandingHeader**: "HyperDX Cloud" → "{brandName} Cloud" (desktop and mobile). Active link color scheme updated for theme consistency. - **Spotlights**: Cloud action label and description use brand name. - **Page titles**: All `<Head><title>` now suffix with current brand (Dashboard, Search, Client Sessions, Chart Explorer, My Team, Create a Dashboard, Alerts, DBDashboardImportPage). ### Copy and errors - **OnboardingModal**: Welcome title and demo server success/error messages use brand name. - **DBSearchPageAlertModal**, **WebhooksSection**, **TeamMembersSection**, **WebhookForm**: "Please contact HyperDX team" → "Please contact {brandName} team". - **SessionsPage**: Empty state and setup instructions ("HyperDX integration", "HyperDX Otel Collector", "HyperDX Browser Integration") use brand name. - **TeamPage**: ClickHouse settings tooltip about windowed queries uses brand name. - **DBChartPage**: AI Assistant alert text ("on the HyperDX server") and Chart Explorer title use brand name. - **SourceForm**: All help text that referred to "HyperDX" (materialized view tooltip, correlated source labels, metrics "not yet fully supported") use brand name. - **HDXMultiSeriesTableChart**: CSV export filename "HyperDX_table_results" → "{brandName}_table_results". ## Testing - With default/HyperDX theme: all existing strings should still read "HyperDX". - With ClickStack theme (e.g. `NEXT_PUBLIC_THEME=clickstack` or dev theme override): titles, welcome text, errors, and help text should show "ClickStack" where appropriate. ## Notes - No changes to SDK imports, type names (e.g. `HyperDXEventType`), or theme definition files. - Brand is deployment-configured via `NEXT_PUBLIC_THEME`; in dev, theme can be switched for verification.
1 parent 38286f6 commit e984e20

21 files changed

Lines changed: 116 additions & 57 deletions
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@hyperdx/app": minor
3+
---
4+
5+
feat: Theme-based branding in UI copy. Replace hardcoded "HyperDX" with the current theme display name so ClickStack deployments show "ClickStack" (e.g. "Welcome to ClickStack", page titles, error messages, help text). Adds `useBrandDisplayName()` hook in ThemeProvider.

‎packages/app/src/AlertsPage.tsx‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import { useQueryClient } from '@tanstack/react-query';
3636
import { ErrorBoundary } from '@/components/Error/ErrorBoundary';
3737
import { PageHeader } from '@/components/PageHeader';
3838

39+
import { useBrandDisplayName } from './theme/ThemeProvider';
3940
import { isAlertSilenceExpired } from './utils/alerts';
4041
import { getWebhookChannelIcon } from './utils/webhookIcons';
4142
import api from './api';
@@ -470,14 +471,15 @@ function AlertCardList({ alerts }: { alerts: AlertsPageItem[] }) {
470471
}
471472

472473
export default function AlertsPage() {
474+
const brandName = useBrandDisplayName();
473475
const { data, isError, isLoading } = api.useAlerts();
474476

475477
const alerts = React.useMemo(() => data?.data || [], [data?.data]);
476478

477479
return (
478480
<div data-testid="alerts-page" className="AlertsPage">
479481
<Head>
480-
<title>Alerts - HyperDX</title>
482+
<title>Alerts - {brandName}</title>
481483
</Head>
482484
<PageHeader>Alerts</PageHeader>
483485
<div className="my-4">

‎packages/app/src/AuthLoadingBlocker.tsx‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { useEffect, useRef, useState } from 'react';
22

3+
import { useBrandDisplayName } from './theme/ThemeProvider';
34
import api from './api';
45

56
export default function AuthLoadingBlocker() {
7+
const brandName = useBrandDisplayName();
68
const { data: meData } = api.useMe();
79

810
// increase number of periods rendered as a loading animation, 1 period per second
@@ -23,7 +25,7 @@ export default function AuthLoadingBlocker() {
2325
zIndex: 2147483647,
2426
}}
2527
>
26-
Loading HyperDX
28+
Loading {brandName}
2729
<span style={{ width: 0 }}>{'.'.repeat(periods)}</span>
2830
</div>
2931
)}

‎packages/app/src/AuthPage.tsx‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
} from '@mantine/core';
1515
import { IconAt, IconLock } from '@tabler/icons-react';
1616

17+
import { useBrandDisplayName } from './theme/ThemeProvider';
1718
import api from './api';
1819
import * as config from './config';
1920
import LandingHeader from './LandingHeader';
@@ -26,6 +27,7 @@ type FormData = {
2627
};
2728

2829
export default function AuthPage({ action }: { action: 'register' | 'login' }) {
30+
const brandName = useBrandDisplayName();
2931
const { data: team, isLoading: teamIsLoading } = api.useTeam();
3032
const router = useRouter();
3133

@@ -55,7 +57,7 @@ export default function AuthPage({ action }: { action: 'register' | 'login' }) {
5557

5658
const verificationSent = msg === 'verify';
5759

58-
const title = `HyperDX - ${isRegister ? 'Sign up' : 'Login'}`;
60+
const title = `${brandName} - ${isRegister ? 'Sign up' : 'Login'}`;
5961

6062
useEffect(() => {
6163
// If an OSS user accidentally lands on /register after already creating a team
@@ -138,7 +140,7 @@ export default function AuthPage({ action }: { action: 'register' | 'login' }) {
138140
: isRegister
139141
? 'Register for '
140142
: 'Login to '}
141-
<span className="text-brand fw-bold">HyperDX</span>
143+
<span className="text-brand fw-bold">{brandName}</span>
142144
</div>
143145
{action === 'login' && (
144146
<div className="text-center mb-2 ">Welcome back!</div>

‎packages/app/src/DBChartPage.tsx‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { SourceSelectControlled } from '@/components/SourceSelect';
3131
import { useChartAssistant } from '@/hooks/ai';
3232
import { withAppNav } from '@/layout';
3333
import { useSources } from '@/source';
34+
import { useBrandDisplayName } from '@/theme/ThemeProvider';
3435
import { parseTimeQuery, useNewTimeQuery } from '@/timeQuery';
3536
import { useLocalStorage } from '@/utils';
3637

@@ -52,6 +53,7 @@ function AIAssistant({
5253
submitRef: React.RefObject<(() => void) | undefined>;
5354
aiAssistantEnabled: boolean;
5455
}) {
56+
const brandName = useBrandDisplayName();
5557
const [opened, setOpened] = useState(false);
5658
const [alertDismissed, setAlertDismissed] = useLocalStorage(
5759
'ai-assistant-alert-dismissed',
@@ -131,8 +133,8 @@ function AIAssistant({
131133
>
132134
<Text size="xs" pt="2px">
133135
New AI Assistant available, enable with configuring the{' '}
134-
<code>ANTHROPIC_API_KEY</code> environment variable on the HyperDX
135-
server.
136+
<code>ANTHROPIC_API_KEY</code> environment variable on the{' '}
137+
{brandName} server.
136138
</Text>
137139
</Alert>
138140
<Divider mt="sm" />
@@ -202,6 +204,7 @@ function AIAssistant({
202204
}
203205

204206
function DBChartExplorerPage() {
207+
const brandName = useBrandDisplayName();
205208
const {
206209
searchedTimeRange,
207210
displayedTimeInputValue,
@@ -229,7 +232,7 @@ function DBChartExplorerPage() {
229232
return (
230233
<Box data-testid="chart-explorer-page" p="sm">
231234
<Head>
232-
<title>Chart Explorer - HyperDX</title>
235+
<title>Chart Explorer - {brandName}</title>
233236
</Head>
234237
<AIAssistant
235238
setConfig={setChartConfig}

‎packages/app/src/DBDashboardImportPage.tsx‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232

3333
import { PageHeader } from './components/PageHeader';
3434
import SelectControlled from './components/SelectControlled';
35+
import { useBrandDisplayName } from './theme/ThemeProvider';
3536
import { useCreateDashboard, useUpdateDashboard } from './dashboard';
3637
import { withAppNav } from './layout';
3738
import { useSources } from './source';
@@ -406,12 +407,13 @@ function Mapping({ input }: { input: Input }) {
406407
}
407408

408409
function DBDashboardImportPage() {
410+
const brandName = useBrandDisplayName();
409411
const [input, setInput] = useState<Input | null>(null);
410412

411413
return (
412414
<div>
413415
<Head>
414-
<title>Create a Dashboard - HyperDX</title>
416+
<title>Create a Dashboard - {brandName}</title>
415417
</Head>
416418
<PageHeader>
417419
<div>Create Dashboard &gt; Import Dashboard</div>

‎packages/app/src/DBDashboardPage.tsx‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ import OnboardingModal from './components/OnboardingModal';
8585
import { Tags } from './components/Tags';
8686
import useDashboardFilters from './hooks/useDashboardFilters';
8787
import { useDashboardRefresh } from './hooks/useDashboardRefresh';
88+
import { useBrandDisplayName } from './theme/ThemeProvider';
8889
import { parseAsStringWithNewLines } from './utils/queryParsers';
8990
import { buildTableRowSearchUrl, DEFAULT_CHART_CONFIG } from './ChartUtils';
9091
import { IS_LOCAL_MODE } from './config';
@@ -675,6 +676,7 @@ function downloadObjectAsJson(object: object, fileName = 'output') {
675676
}
676677

677678
function DBDashboardPage({ presetConfig }: { presetConfig?: Dashboard }) {
679+
const brandName = useBrandDisplayName();
678680
const confirm = useConfirm();
679681

680682
const router = useRouter();
@@ -1010,7 +1012,7 @@ function DBDashboardPage({ presetConfig }: { presetConfig?: Dashboard }) {
10101012
return (
10111013
<Box p="sm" data-testid="dashboard-page">
10121014
<Head>
1013-
<title>Dashboard – HyperDX</title>
1015+
<title>Dashboard – {brandName}</title>
10141016
</Head>
10151017
<OnboardingModal />
10161018
<EditTileModal

‎packages/app/src/DBSearchPage.tsx‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ import {
108108
useSource,
109109
useSources,
110110
} from '@/source';
111-
import { useAppTheme } from '@/theme/ThemeProvider';
111+
import { useAppTheme, useBrandDisplayName } from '@/theme/ThemeProvider';
112112
import {
113113
parseRelativeTimeQuery,
114114
parseTimeQuery,
@@ -806,6 +806,7 @@ const queryStateMap = {
806806
};
807807

808808
function DBSearchPage() {
809+
const brandName = useBrandDisplayName();
809810
// Next router is laggy behind window.location, which causes race
810811
// conditions with useQueryStates, so we'll parse it directly
811812
const paths = window.location.pathname.split('/');
@@ -1577,7 +1578,7 @@ function DBSearchPage() {
15771578
>
15781579
<Head>
15791580
<title>
1580-
{savedSearch ? `${savedSearch.name} Search` : 'Search'} - HyperDX
1581+
{savedSearch ? `${savedSearch.name} Search` : 'Search'} - {brandName}
15811582
</title>
15821583
</Head>
15831584
{!IS_LOCAL_MODE && isAlertModalOpen && (

‎packages/app/src/DBSearchPageAlertModal.tsx‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import { useQueryClient } from '@tanstack/react-query';
3939
import { useCreateSavedSearch } from '@/savedSearch';
4040
import { useSavedSearch } from '@/savedSearch';
4141
import { useSource } from '@/source';
42+
import { useBrandDisplayName } from '@/theme/ThemeProvider';
4243
import {
4344
ALERT_CHANNEL_OPTIONS,
4445
ALERT_INTERVAL_OPTIONS,
@@ -266,6 +267,7 @@ export const DBSearchPageAlertModal = ({
266267
onClose: () => void;
267268
open: boolean;
268269
}) => {
270+
const brandName = useBrandDisplayName();
269271
const queryClient = useQueryClient();
270272
const createAlert = api.useCreateAlert();
271273
const updateAlert = api.useUpdateAlert();
@@ -350,7 +352,7 @@ export const DBSearchPageAlertModal = ({
350352
} catch (error) {
351353
notifications.show({
352354
color: 'red',
353-
message: 'Something went wrong. Please contact HyperDX team.',
355+
message: `Something went wrong. Please contact ${brandName} team.`,
354356
autoClose: 5000,
355357
});
356358
}
@@ -369,7 +371,7 @@ export const DBSearchPageAlertModal = ({
369371
} catch (error) {
370372
notifications.show({
371373
color: 'red',
372-
message: 'Something went wrong. Please contact HyperDX team.',
374+
message: `Something went wrong. Please contact ${brandName} team.`,
373375
autoClose: 5000,
374376
});
375377
}

‎packages/app/src/HDXMultiSeriesTableChart.tsx‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { useVirtualizer } from '@tanstack/react-virtual';
1818
import { CsvExportButton } from './components/CsvExportButton';
1919
import TableHeader from './components/DBTable/TableHeader';
2020
import { useCsvExport } from './hooks/useCsvExport';
21+
import { useBrandDisplayName } from './theme/ThemeProvider';
2122
import { UNDEFINED_WIDTH } from './tableUtils';
2223
import type { NumberFormat } from './types';
2324
import { formatNumber } from './utils';
@@ -51,6 +52,7 @@ export const Table = ({
5152
onSortingChange: (sorting: SortingState) => void;
5253
variant?: TableVariant;
5354
}) => {
55+
const brandName = useBrandDisplayName();
5456
const MIN_COLUMN_WIDTH_PX = 100;
5557
//we need a reference to the scrolling element for logic down below
5658
const tableContainerRef = useRef<HTMLDivElement>(null);
@@ -254,7 +256,7 @@ export const Table = ({
254256
</UnstyledButton>
255257
<CsvExportButton
256258
data={csvData}
257-
filename="HyperDX_table_results"
259+
filename={`${brandName}_table_results`}
258260
className="fs-8 ms-2"
259261
title="Download table as CSV"
260262
>

0 commit comments

Comments
 (0)