fix(ai): onboarding welcome uses each brand's own logo (no hardcoded Hanzo H / tagline)

Read brandConfig.logo inside OnboardingLayout (was a module-level useBrand()
frozen on the default brand, forcing visor.svg's Hanzo "H" onto Zoo/Lux).
Drop the broken right-column hero preview; tagline is now opt-in via
brandConfig.tagline (empty default — removes the old hardcoded "the way, the
truth, the life"). Welcome title uses {{appName}} so no brand name leaks.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-17 06:02:25 +00:00
co-authored by Claude Opus 4.8
parent 3909206e20
commit b4db03d347
3 changed files with 32 additions and 29 deletions
@@ -10,17 +10,21 @@ export type OnboardingLayoutProps = React.PropsWithChildren<
React.HTMLAttributes<HTMLDivElement>
>;
const logoSrc =
useBrand().brand === 'zoo' ? './zoo-logo.svg' : './visor.svg';
// TODO: zoo-onboarding.png is currently the rounded app icon as a stand-in.
// Replace with a proper Zoo onboarding hero image when art is available.
const heroSrc =
useBrand().brand === 'zoo' ? './zoo-onboarding.png' : './onboarding.png';
const OnboardingLayout = ({ className, ...props }: OnboardingLayoutProps) => {
const { tapCount, setTapCount, setShowLocalNodeOption } =
useContext(LogoTapContext);
// Brand-driven logo + (optional) tagline. Read INSIDE the component so each
// app's injected brand (set by <HanzoAI {...brandConfig}/> before mount) is
// honored — the previous module-level useBrand() froze on the default brand
// and forced the Hanzo "H" (visor.svg) onto Zoo/Lux. The brand ships its own
// mark via brandConfig.logo; nothing brand-specific is hardcoded here.
const brand = useBrand();
const logoSrc = brand.logo?.dark ?? brand.logo?.light ?? '/app-logo.png';
// Tagline is opt-in: only brands that set brandConfig.tagline show one. No
// brand carries the old hardcoded "the way, the truth, the life" copy.
const tagline = (brand as { tagline?: string }).tagline;
const handleLogoTap = () => {
const newCount = tapCount + 1;
setTapCount(newCount);
@@ -33,39 +37,34 @@ const OnboardingLayout = ({ className, ...props }: OnboardingLayoutProps) => {
return (
<div
className={cn(
'bg-bg-dark relative mx-auto grid h-full grid-cols-2 flex-col-reverse items-center px-[48px]',
'bg-bg-dark relative mx-auto flex h-full items-center justify-center px-[48px]',
className,
)}
{...props}
>
<UpdateBanner />
<div className="flex h-[calc(100dvh-100px)] items-center justify-center">
<div className="flex h-[calc(100dvh-100px)] w-full items-center justify-center">
<div className="mx-auto flex h-[600px] w-full max-w-lg flex-col gap-12">
<img
alt={`${useBrand().name} logo`}
className="w-24 cursor-pointer"
data-cy="hanzo-logo"
onClick={handleLogoTap}
src={logoSrc}
/>
<div className="flex flex-col gap-3">
<img
alt={`${brand.name} logo`}
className="w-24 cursor-pointer"
data-cy="app-logo"
onClick={handleLogoTap}
src={logoSrc}
/>
{tagline ? (
<p className="text-xs uppercase tracking-[0.2em] text-white/60">
{tagline}
</p>
) : null}
</div>
<div className="flex-1">
<Outlet />
</div>
</div>
</div>
<div className="grid h-full place-items-center">
<div className="relative size-full">
<div className="absolute left-14 z-10 flex aspect-square size-full items-center object-left bg-blend-darken">
<img
alt={`${useBrand().name} onboarding`}
className="size-full max-h-[70vh] object-cover object-left"
data-cy="onboarding-logo"
src={heroSrc}
/>
</div>
</div>
</div>
</div>
);
};
+4
View File
@@ -13,6 +13,10 @@ export interface BrandConfig {
productName: string;
identifier: string; // bundle id, e.g. com.lux.desktop
logo: { light: string; dark: string; favicon: string };
/** Optional small-caps tagline under the onboarding logo. Empty/absent for
* every brand by default — set it per-brand to opt in. (Replaces the old
* hardcoded "the way, the truth, the life".) */
tagline?: string;
colors: { primary: string; bg: string; fg: string };
hosts: string[];
storeUrl: { mac: string; win: string; ios: string; android: string };
+1 -1
View File
@@ -14,7 +14,7 @@ export default {
enterToSend: '<span>Enter</span> to send',
},
desktop: {
welcome: 'Welcome to Hanzo',
welcome: 'Welcome to {{appName}}',
welcomeDescription:
'<b>Hanzo lets you build AI agents in minutes — fast, private, and secure.</b> Run locally, collaborate through a decentralized network, and create AI workflows effortlessly. ',
localAI: 'Hanzo Local AI',