Files
explore/lib/white-label.ts
T
hanzo-dev eda38ce65c feat: multi-brand build matrix + white-label support
Build the same source four ways from one repo:

- ghcr.io/luxfi/explore         (lux brand, default)
- ghcr.io/luxfi/explore-hanzo   (hanzo brand)
- ghcr.io/luxfi/explore-zoo     (zoo brand)
- ghcr.io/luxfi/explore-pars    (pars brand)

Each is built for linux/amd64 + linux/arm64 in parallel on hanzo ARC
runners (no QEMU), then merged into a multi-arch manifest.

Brand selection at build time via NEXT_PUBLIC_BRAND, with all
brand-specific assets (logo, favicon, theme, IAM URL) loaded from
NEXT_PUBLIC_* env vars — no hardcoded brand strings in source.

External operators set NEXT_PUBLIC_BRAND=other and supply their own
NEXT_PUBLIC_* env vars (see .env.example.external). The repo carries
no third-party trademarks.

Files:
- lib/white-label.ts                             brand detection + helpers
- .env.example.{lux,hanzo,zoo,pars,external}     deploy templates
- .github/workflows/build-lux.yml                4-brand × 2-arch matrix
- Dockerfile                                     accept NEXT_PUBLIC_BRAND
- configs/app/chainRegistry.ts                   add SPC + Pars devnet,
                                                 chainId fields, white-label
                                                 chain builder
2026-05-05 20:50:55 -07:00

68 lines
2.2 KiB
TypeScript

// White-label brand detection.
//
// Source code in this repo is brand-neutral. Brand selection happens at
// deploy time via `NEXT_PUBLIC_BRAND` env var or by hostname inspection.
// All brand-specific assets (logo, title, favicon, color theme, IAM URL)
// load from `NEXT_PUBLIC_*` env vars — no hardcoded brand strings here.
//
// Supported brands:
// - lux (default)
// - hanzo
// - zoo
// - pars
// - other (any external white-label deploy: branding from env vars)
//
// External deployments select their brand by setting NEXT_PUBLIC_BRAND in
// the runtime environment. They do NOT add their brand here — keeping this
// repo free of any third-party trademarks.
import { getEnvValue } from 'configs/app/utils';
export type WhiteLabelBrand = 'lux' | 'hanzo' | 'zoo' | 'pars' | 'other';
const BRAND_HOSTNAME_SUFFIXES: ReadonlyArray<{ readonly suffix: string; readonly brand: WhiteLabelBrand }> = [
{ suffix: '.lux.network', brand: 'lux' },
{ suffix: '.lux.build', brand: 'lux' },
{ suffix: '.hanzo.ai', brand: 'hanzo' },
{ suffix: '.hanzo.network', brand: 'hanzo' },
{ suffix: '.zoo.ngo', brand: 'zoo' },
{ suffix: '.zoo.network', brand: 'zoo' },
{ suffix: '.pars.network', brand: 'pars' },
];
export function getWhiteLabelBrand(hostname?: string): WhiteLabelBrand {
// 1. Explicit env var wins (CI/CD, k8s ConfigMap)
const envBrand = getEnvValue('NEXT_PUBLIC_BRAND');
if (envBrand) {
const normalized = envBrand.toLowerCase();
if (
normalized === 'lux' ||
normalized === 'hanzo' ||
normalized === 'zoo' ||
normalized === 'pars' ||
normalized === 'other'
) {
return normalized;
}
// Any unknown brand string → 'other' (env-driven white-label)
return 'other';
}
// 2. Hostname-based detection
const host = (hostname || (typeof window !== 'undefined' ? window.location.hostname : '')).toLowerCase();
if (host) {
for (const entry of BRAND_HOSTNAME_SUFFIXES) {
if (host === entry.suffix.slice(1) || host.endsWith(entry.suffix)) {
return entry.brand;
}
}
}
// 3. Default
return 'lux';
}
export function isWhiteLabelExternal(brand: WhiteLabelBrand): boolean {
return brand === 'other';
}